From 8c730c0694bd0df80237a2f7a7db4d11a480e199 Mon Sep 17 00:00:00 2001 From: Juan Picado Date: Thu, 17 Sep 2020 06:48:16 +0200 Subject: [PATCH] refactor: max-len and printWidth to 100 (#1941) * refactor: max-len and printWidth to 100 * chore: ci specific pnpm version * fix: add types peer package literally get rid of types package --- .dockerignore | 1 + .eslintrc | 2 +- .github/workflows/changesets.yml | 2 +- .github/workflows/ci.yml | 2 +- .prettierrc.json | 2 +- Dockerfile | 4 +- package.json | 4 +- packages/api/package.json | 1 - packages/api/src/dist-tags.ts | 48 ++++- packages/api/src/index.ts | 17 +- packages/api/src/package.ts | 35 +++- packages/api/src/ping.ts | 8 +- packages/api/src/publish.ts | 86 ++++++-- packages/api/src/star.ts | 13 +- packages/api/src/stars.ts | 36 ++-- packages/api/src/user.ts | 45 +++- packages/api/src/v1/profile.ts | 19 +- packages/api/src/v1/search.ts | 12 +- packages/api/src/v1/token.ts | 62 ++++-- packages/api/src/whoami.ts | 2 +- packages/api/test/integration/_helper.ts | 17 +- packages/api/test/integration/package.spec.ts | 12 +- packages/api/test/integration/publish.spec.ts | 20 +- packages/api/test/integration/user.spec.ts | 74 ++++--- packages/api/test/integration/whoami.spec.ts | 13 +- packages/api/test/unit/publish.spec.ts | 8 +- packages/api/tsconfig.json | 3 - packages/api/types/custom.d.ts | 5 + packages/auth/package.json | 1 - packages/auth/src/auth.ts | 143 +++++++++++-- packages/auth/src/index.ts | 2 +- packages/auth/src/utils.ts | 44 +++- packages/auth/test/auth-utils.spec.ts | 142 +++++++++++-- packages/auth/test/auth.spec.ts | 11 +- packages/cli/src/cli.ts | 12 +- packages/cli/src/commands/init.ts | 9 +- packages/cli/src/utils.ts | 3 +- packages/commons/src/constants.ts | 3 +- packages/commons/src/helpers/pkg.ts | 9 +- packages/config/package.json | 3 - packages/config/src/config-path.ts | 20 +- packages/config/src/config.ts | 18 +- packages/core/commons-api/src/index.ts | 8 +- packages/core/file-locking/src/readFile.ts | 6 +- packages/core/file-locking/tests/lock.spec.ts | 8 +- packages/core/htpasswd/src/htpasswd.ts | 16 +- packages/core/htpasswd/src/utils.ts | 15 +- packages/core/htpasswd/tests/utils.test.ts | 23 +- .../core/local-storage/src/local-database.ts | 49 ++++- packages/core/local-storage/src/local-fs.ts | 18 +- packages/core/local-storage/src/pkg-utils.ts | 5 +- packages/core/local-storage/src/utils.ts | 5 +- .../local-storage/tests/__fixtures__/pkg.js | 3 +- .../tests/local-database.test.ts | 44 +++- .../core/local-storage/tests/local-fs.test.ts | 75 +++++-- packages/core/readme/tests/readme.spec.ts | 86 ++++++-- packages/core/types/index.d.ts | 26 ++- packages/hooks/package.json | 1 - packages/hooks/src/notify.ts | 32 ++- packages/hooks/test/notify.spec.ts | 8 +- packages/hooks/test/request.spec.ts | 14 +- packages/loaders/package.json | 1 - packages/loaders/src/plugin-loader.ts | 27 ++- packages/loaders/test/plugin_loader.spec.ts | 12 +- packages/logger-prettify/src/formatter.ts | 10 +- .../logger-prettify/test/formatter.spec.ts | 7 +- packages/logger/src/logger.ts | 7 +- packages/middleware/package.json | 7 +- packages/middleware/src/middleware.ts | 117 +++++++++-- packages/mock/package.json | 1 - packages/mock/src/config.ts | 4 +- packages/mock/src/mock-api.ts | 75 ++++++- packages/mock/src/mock.ts | 7 +- packages/mock/src/server.ts | 11 +- packages/mock/src/server_process.ts | 7 +- packages/mock/src/utils-test.ts | 9 +- packages/node-api/src/bootstrap.d.ts | 16 +- packages/node-api/src/bootstrap.ts | 41 +++- packages/node-api/src/cli-utils.ts | 4 +- packages/node-api/src/experiments.ts | 8 +- packages/node-api/src/https.ts | 5 +- packages/node-api/test/node-api.spec.ts | 31 +-- packages/proxy/package.json | 1 - packages/proxy/src/up-storage.ts | 96 +++++++-- packages/proxy/src/uplink-util.ts | 3 +- packages/proxy/test/headers.auth.spec.ts | 8 +- packages/server/package.json | 1 - packages/server/src/debug/index.ts | 8 +- packages/server/src/server.ts | 36 +++- .../server/test/api/helpers/publish-api.js | 3 +- packages/server/test/api/helpers/utils.ts | 17 +- packages/server/test/api/index.spec.ts | 107 ++++++++-- packages/server/test/jwt/index.spec.ts | 39 +++- packages/server/test/profile/index.spec.ts | 16 +- packages/server/test/proxy/index.spec.ts | 17 +- packages/server/test/storage/index.spec.ts | 6 +- packages/server/test/token/index.spec.ts | 17 +- packages/server/test/web/index.spec.ts | 14 +- .../test/web/partials/forbidden-place.js | 3 +- .../server/test/web/partials/publish-api.js | 3 +- packages/server/types/custom.d.ts | 5 + packages/store/package.json | 1 - packages/store/src/local-storage.ts | 85 ++++++-- packages/store/src/search.ts | 13 +- packages/store/src/storage-utils.ts | 31 ++- packages/store/src/storage.ts | 165 ++++++++++++--- packages/store/test/local-storage.spec.ts | 64 ++++-- packages/store/test/merge.dist.tags.spec.ts | 7 +- packages/store/test/storage-utils.spec.ts | 7 +- packages/types/index.ts | 148 ------------- packages/types/package.json | 2 + packages/types/src/index.ts | 196 ++++++++++++++++++ packages/types/tsconfig.build.json | 8 + packages/types/tsconfig.json | 2 +- packages/utils/package.json | 1 - packages/utils/src/auth-utils.ts | 72 +++++-- packages/utils/src/config-utils.ts | 36 +++- packages/utils/src/crypto-utils.ts | 6 +- packages/utils/src/utils.ts | 39 +++- packages/utils/test/auth-utils.spec.ts | 155 ++++++++------ packages/utils/test/config-utils.spec.ts | 24 ++- packages/utils/test/utils.spec.ts | 21 +- packages/verdaccio/jest.config.js | 7 +- .../test/functional/adduser/adduser.js | 5 +- .../verdaccio/test/functional/basic/basic.ts | 46 +++- .../test/functional/notifications/notify.ts | 16 +- .../test/functional/package/scoped.ts | 8 +- .../test/functional/performance/race.ts | 10 +- .../verdaccio/test/functional/plugins/auth.ts | 54 ++++- .../test/functional/sanity/mirror.ts | 10 +- .../test/functional/sanity/nullstorage.ts | 14 +- .../test/functional/sanity/racycrash.ts | 4 +- .../test/functional/sanity/security.ts | 9 +- .../test/functional/scenarios/gh29.ts | 5 +- .../test/functional/search/simple.search.ts | 5 +- .../verdaccio/test/functional/tags/addtag.ts | 10 +- .../test/functional/tags/dist-tags-merge.ts | 15 +- .../test/functional/uplinks/cache.ts | 10 +- .../plugins/auth/example.auth.plugin.ts | 12 +- .../middleware/example.middleware.plugin.ts | 11 +- .../plugins/storage/example.storage.plugin.ts | 19 +- packages/verdaccio/test/unit/__helper/api.ts | 66 +++++- .../verdaccio/test/unit/__helper/utils.ts | 3 +- .../test/unit/partials/forbidden-place.js | 3 +- .../unit/partials/storage/verdaccio.db.json | 5 +- packages/web/package.json | 1 - packages/web/src/endpoint/package.ts | 68 ++++-- packages/web/src/endpoint/search.ts | 15 +- packages/web/src/endpoint/user.ts | 9 +- packages/web/src/web-api.ts | 3 +- packages/web/src/web-utils.ts | 7 +- pnpm-lock.yaml | 30 +-- test/e2e-cli/setup/setup.ts | 5 +- test/e2e-cli/test/__partials/npm_commands.ts | 10 +- test/e2e-cli/test/core/info.spec.ts | 7 +- test/e2e-cli/test/core/listen.spec.ts | 5 +- test/e2e-cli/test/install/install.spec.ts | 26 ++- test/e2e-cli/utils/process.ts | 7 +- tsconfig.base.json | 11 +- website/config/sidebar.json | 10 +- website/docs/logger.md | 8 +- website/docs/node-api.md | 17 +- website/docs/plugin-auth.md | 6 +- website/docs/plugin-storage.md | 6 +- .../src/components/AppDrawer/AppDrawer.tsx | 18 +- website/src/components/Header.tsx | 6 +- .../components/PageContext/PageContext.tsx | 20 +- website/src/components/Seo.tsx | 10 +- website/src/library/wrapRootElement.tsx | 4 +- website/src/templates/docPage.tsx | 7 +- website/src/templates/frontpage.tsx | 15 +- website/src/utils/cli-utils.ts | 10 +- 172 files changed, 3044 insertions(+), 949 deletions(-) create mode 100644 packages/types/src/index.ts create mode 100644 packages/types/tsconfig.build.json diff --git a/.dockerignore b/.dockerignore index cf6dedae0..1e7af903c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -21,6 +21,7 @@ # do not copy over node_modules we will run `npm install` anyway node_modules +website # output from test runs and similar things *.log diff --git a/.eslintrc b/.eslintrc index 9e7e7589d..03bbb0741 100644 --- a/.eslintrc +++ b/.eslintrc @@ -58,7 +58,7 @@ "camelcase": "off", "guard-for-in": "error", "new-cap": "error", - "max-len": ["warn", 160], + "max-len": ["warn", 100], "no-console": ["error", { "allow": ["warn"] }], "no-constant-condition": "error", "no-debugger": "error", diff --git a/.github/workflows/changesets.yml b/.github/workflows/changesets.yml index 19cd39e50..21e0c8230 100644 --- a/.github/workflows/changesets.yml +++ b/.github/workflows/changesets.yml @@ -33,7 +33,7 @@ jobs: node-version: 14 - name: install pnpm - run: npm install pnpm@5.5.2 -g + run: npm i pnpm@5.5.2 -g - name: setup pnpm config run: pnpm config set store-dir $PNPM_CACHE_FOLDER diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef0e5576b..f85d843ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: with: node_version: ${{ matrix.node_version }} - name: Install pnpm - run: npm i -g pnpm + run: npm i pnpm@5.5.12 -g - name: Install run: pnpm recursive install - name: Format diff --git a/.prettierrc.json b/.prettierrc.json index 83ab90ca3..34f4adcfb 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,7 +1,7 @@ { "endOfLine": "lf", "useTabs": false, - "printWidth": 160, + "printWidth": 100, "tabWidth": 2, "singleQuote": true, "bracketSpacing": true, diff --git a/Dockerfile b/Dockerfile index ed9403952..8a57e9d42 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,10 +14,10 @@ COPY . . RUN npm -g i pnpm@latest && \ pnpm config set registry $VERDACCIO_BUILD_REGISTRY && \ - pnpm recursive install --frozen-lockfile && \ + pnpm recursive install --frozen-lockfile --ignore-scripts && \ pnpm run build && \ pnpm run lint && \ - pnpm install --prod + pnpm install --prod --ignore-scripts FROM node:12.18.3-alpine LABEL maintainer="https://github.com/verdaccio/verdaccio" diff --git a/package.json b/package.json index 65d44ea32..b46f03cb2 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "selfsigned": "1.10.7", "standard-version": "8.0.0", "supertest": "4.0.2", - "typescript": ">=3.3.1 <3.10.0", + "typescript": "^3.9.7", "verdaccio": "latest", "verdaccio-audit": "latest", "verdaccio-auth-memory": "latest", @@ -101,8 +101,6 @@ "verdaccio-memory": "latest" }, "scripts": { - "start": "node packages/verdaccio/debug/bootstrap.js", - "debug": "node --inspect packages/verdaccio/debug/bootstrap.js", "dev": "cross-env BABEL_ENV=registry babel-node --extensions \".ts,.tsx\" packages/cli/src", "clean": "pnpm recursive run clean", "build": "pnpm recursive run build", diff --git a/packages/api/package.json b/packages/api/package.json index 1a14e5a5a..4c50f9f16 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -40,7 +40,6 @@ }, "devDependencies": { "@verdaccio/config": "workspace:5.0.0-alpha.0", - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/server": "workspace:5.0.0-alpha.0", "@verdaccio/types": "workspace:*", "body-parser": "1.19.0", diff --git a/packages/api/src/dist-tags.ts b/packages/api/src/dist-tags.ts index 23a551381..d8b21ec4a 100644 --- a/packages/api/src/dist-tags.ts +++ b/packages/api/src/dist-tags.ts @@ -6,13 +6,17 @@ import { media, allow } from '@verdaccio/middleware'; import { API_MESSAGE, HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons'; import { VerdaccioError } from '@verdaccio/commons-api'; import { Package } from '@verdaccio/types'; - -// @ts-ignore -import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; +import { IStorageHandler } from '@verdaccio/store'; +import { IAuth } from '@verdaccio/auth'; +import { $NextFunctionVer, $RequestExtend, $ResponseExtend } from '../types/custom'; export default function (route: Router, auth: IAuth, storage: IStorageHandler): void { const can = allow(auth); - const tag_package_version = function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): $NextFunctionVer { + const tag_package_version = function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): $NextFunctionVer { if (_.isString(req.body) === false) { return next('route'); } @@ -31,11 +35,25 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler): // tagging a package. route.put('/:package/:tag', can('publish'), media(mime.getType('json')), tag_package_version); - route.post('/-/package/:package/dist-tags/:tag', can('publish'), media(mime.getType('json')), tag_package_version); + route.post( + '/-/package/:package/dist-tags/:tag', + can('publish'), + media(mime.getType('json')), + tag_package_version + ); - route.put('/-/package/:package/dist-tags/:tag', can('publish'), media(mime.getType('json')), tag_package_version); + route.put( + '/-/package/:package/dist-tags/:tag', + can('publish'), + media(mime.getType('json')), + tag_package_version + ); - route.delete('/-/package/:package/dist-tags/:tag', can('publish'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.delete('/-/package/:package/dist-tags/:tag', can('publish'), function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { const tags = {}; tags[req.params.tag] = null; storage.mergeTags(req.params.package, tags, function (err: VerdaccioError): $NextFunctionVer { @@ -49,7 +67,11 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler): }); }); - route.get('/-/package/:package/dist-tags', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.get('/-/package/:package/dist-tags', can('access'), function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { storage.getPackage({ name: req.params.package, uplinksLook: true, @@ -64,8 +86,14 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler): }); }); - 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 { + 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); } diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 311d7b21f..298d77477 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1,8 +1,15 @@ import _ from 'lodash'; import express, { Express } from 'express'; -import { match, validateName, validatePackage, encodeScopePackage, antiLoop } from '@verdaccio/middleware'; -import { IAuth, IStorageHandler } from '@verdaccio/dev-types'; +import { + match, + validateName, + validatePackage, + encodeScopePackage, + antiLoop, +} from '@verdaccio/middleware'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; import { Config } from '@verdaccio/types'; import bodyParser from 'body-parser'; @@ -18,7 +25,11 @@ import profile from './v1/profile'; import token from './v1/token'; import v1Search from './v1/search'; -export default function (config: Config, auth: IAuth, storage: IStorageHandler): Express.Application { +export default function ( + config: Config, + auth: IAuth, + storage: IStorageHandler +): Express.Application { /* eslint new-cap:off */ const app = express.Router(); /* eslint new-cap:off */ diff --git a/packages/api/src/package.ts b/packages/api/src/package.ts index 3dc21e491..88bb2e158 100644 --- a/packages/api/src/package.ts +++ b/packages/api/src/package.ts @@ -6,11 +6,19 @@ import { allow } from '@verdaccio/middleware'; import { convertDistRemoteToLocalTarballUrls, getVersion, ErrorCode } from '@verdaccio/utils'; import { HEADERS, DIST_TAGS, API_ERROR } from '@verdaccio/dev-commons'; import { Config, Package } from '@verdaccio/types'; -import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; +import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '../types/custom'; const debug = buildDebug('verdaccio:api:package'); -const downloadStream = (packageName: string, filename: string, storage: any, req: $RequestExtend, res: $ResponseExtend): void => { +const downloadStream = ( + packageName: string, + filename: string, + storage: any, + req: $RequestExtend, + res: $ResponseExtend +): void => { const stream = storage.getTarball(packageName, filename); stream.on('content-length', function (content): void { @@ -25,10 +33,19 @@ const downloadStream = (packageName: string, filename: string, storage: any, req stream.pipe(res); }; -export default function (route: Router, auth: IAuth, storage: IStorageHandler, config: Config): void { +export default function ( + route: Router, + auth: IAuth, + storage: IStorageHandler, + config: Config +): void { const can = allow(auth); // TODO: anonymous user? - route.get('/:package/:version?', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.get('/:package/:version?', can('access'), function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { debug('init package by version'); const name = req.params.package; const getPackageMetaCallback = function (err, metadata: Package): void { @@ -81,13 +98,19 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c }); }); - route.get('/:scopedPackage/-/:scope/:filename', can('access'), function (req: $RequestExtend, res: $ResponseExtend): void { + 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 { + route.get('/:package/-/:filename', can('access'), function ( + req: $RequestExtend, + res: $ResponseExtend + ): void { downloadStream(req.params.package, req.params.filename, storage, req, res); }); } diff --git a/packages/api/src/ping.ts b/packages/api/src/ping.ts index 2a51c63d9..d6adfbc25 100644 --- a/packages/api/src/ping.ts +++ b/packages/api/src/ping.ts @@ -1,8 +1,12 @@ import { Router } from 'express'; -import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '@verdaccio/dev-types'; +import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '../types/custom'; export default function (route: Router): void { - route.get('/-/ping', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { + route.get('/-/ping', function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ) { next({}); }); } diff --git a/packages/api/src/publish.ts b/packages/api/src/publish.ts index 8c0ea9286..2be4dfc82 100644 --- a/packages/api/src/publish.ts +++ b/packages/api/src/publish.ts @@ -4,20 +4,33 @@ import mime from 'mime'; import { Router } from 'express'; import buildDebug from 'debug'; -import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; import { API_MESSAGE, HEADERS, DIST_TAGS, API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; -import { validateMetadata, isObject, ErrorCode, hasDiffOneKey, isRelatedToDeprecation } from '@verdaccio/utils'; +import { + validateMetadata, + isObject, + ErrorCode, + hasDiffOneKey, + isRelatedToDeprecation, +} from '@verdaccio/utils'; import { media, expectJson, allow } from '@verdaccio/middleware'; import { notify } from '@verdaccio/hooks'; import { Config, Callback, MergeTags, Version, Package } from '@verdaccio/types'; import { logger } from '@verdaccio/logger'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; +import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '../types/custom'; import star from './star'; import { isPublishablePackage } from './utils'; const debug = buildDebug('verdaccio:api:publish'); -export default function publish(router: Router, auth: IAuth, storage: IStorageHandler, config: Config): void { +export default function publish( + router: Router, + auth: IAuth, + storage: IStorageHandler, + config: Config +): void { const can = allow(auth); /** @@ -79,7 +92,13 @@ export default function publish(router: Router, auth: IAuth, storage: IStorageHa } * */ - router.put('/:package/:_rev?/:revision?', can('publish'), media(mime.getType('json')), expectJson, publishPackage(storage, config, auth)); + router.put( + '/:package/:_rev?/:revision?', + can('publish'), + media(mime.getType('json')), + expectJson, + publishPackage(storage, config, auth) + ); /** * Un-publishing an entire package. @@ -92,13 +111,29 @@ export default function publish(router: Router, auth: IAuth, storage: IStorageHa router.delete('/:package/-rev/*', can('unpublish'), unPublishPackage(storage)); // removing a tarball - router.delete('/:package/-/:filename/-rev/:revision', can('unpublish'), can('publish'), removeTarball(storage)); + router.delete( + '/:package/-/:filename/-rev/:revision', + can('unpublish'), + can('publish'), + removeTarball(storage) + ); // uploading package tarball - router.put('/:package/-/:filename/*', can('publish'), media(HEADERS.OCTET_STREAM), uploadPackageTarball(storage)); + router.put( + '/:package/-/:filename/*', + can('publish'), + media(HEADERS.OCTET_STREAM), + uploadPackageTarball(storage) + ); // adding a version - router.put('/:package/:version/-tag/:tag', can('publish'), media(mime.getType('json')), expectJson, addVersion(storage)); + router.put( + '/:package/:version/-tag/:tag', + can('publish'), + media(mime.getType('json')), + expectJson, + addVersion(storage) + ); } /** @@ -117,7 +152,12 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I const createTarball = function (filename: string, data, cb: Callback): void { const stream = storage.addTarball(packageName, filename); stream.on('error', function (err) { - debug('error on stream a tarball %o for %o with error %o', filename, packageName, err.message); + debug( + 'error on stream a tarball %o for %o with error %o', + filename, + packageName, + err.message + ); cb(err); }); stream.on('success', function () { @@ -172,7 +212,11 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I // npm-registry-client 0.3+ embeds tarball into the json upload // https://github.com/isaacs/npm-registry-client/commit/e9fbeb8b67f249394f735c74ef11fe4720d46ca0 // issue https://github.com/rlidwka/sinopia/issues/31, dealing with it here: - const isInvalidBodyFormat = isObject(_attachments) === false || hasDiffOneKey(_attachments) || isObject(versions) === false || hasDiffOneKey(versions); + const isInvalidBodyFormat = + isObject(_attachments) === false || + hasDiffOneKey(_attachments) || + isObject(versions) === false || + hasDiffOneKey(versions); if (isInvalidBodyFormat) { // npm is doing something strange again @@ -190,7 +234,9 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I // at this point document is either created or existed before const [firstAttachmentKey] = Object.keys(_attachments); - createTarball(Path.basename(firstAttachmentKey), _attachments[firstAttachmentKey], function (error) { + createTarball(Path.basename(firstAttachmentKey), _attachments[firstAttachmentKey], function ( + error + ) { debug('creating a tarball %o', firstAttachmentKey); if (error) { debug('error on create a tarball for %o with error %o', packageName, error.message); @@ -199,7 +245,8 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I const versionToPublish = Object.keys(versions)[0]; - versions[versionToPublish].readme = _.isNil(metadataCopy.readme) === false ? String(metadataCopy.readme) : ''; + versions[versionToPublish].readme = + _.isNil(metadataCopy.readme) === false ? String(metadataCopy.readme) : ''; createVersion(versionToPublish, versions[versionToPublish], function (error) { if (error) { @@ -214,7 +261,12 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I } try { - await notify(metadataCopy, config, req.remote_user, `${metadataCopy.name}@${versionToPublish}`); + await notify( + metadataCopy, + config, + req.remote_user, + `${metadataCopy.name}@${versionToPublish}` + ); } catch (error) { debug('error on notify add a new tag %o', `${metadataCopy.name}@${versionToPublish}`); logger.error({ error }, 'notify batch service has failed: @{error}'); @@ -295,14 +347,20 @@ export function removeTarball(storage: IStorageHandler) { const packageName = req.params.package; const { filename, revision } = req.params; - logger.debug({ packageName, filename, revision }, `removing a tarball for @{packageName}-@{tarballName}-@{revision}`); + logger.debug( + { packageName, filename, revision }, + `removing a tarball for @{packageName}-@{tarballName}-@{revision}` + ); storage.removeTarball(packageName, filename, revision, function (err) { if (err) { return next(err); } res.status(HTTP_STATUS.CREATED); - logger.debug({ packageName, filename, revision }, `success remove tarball for @{packageName}-@{tarballName}-@{revision}`); + logger.debug( + { packageName, filename, revision }, + `success remove tarball for @{packageName}-@{tarballName}-@{revision}` + ); return next({ ok: API_MESSAGE.TARBALL_REMOVED }); }); }; diff --git a/packages/api/src/star.ts b/packages/api/src/star.ts index ba4062e70..924d8d2fa 100644 --- a/packages/api/src/star.ts +++ b/packages/api/src/star.ts @@ -1,14 +1,16 @@ import { USERS, HTTP_STATUS } from '@verdaccio/dev-commons'; import { Response } from 'express'; import _ from 'lodash'; -import { logger } from '@verdaccio/logger'; import buildDebug from 'debug'; -import { $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; +import { IStorageHandler } from '@verdaccio/store'; +import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '../types/custom'; const debug = buildDebug('verdaccio:api:publish:star'); -export default function (storage: IStorageHandler): (req: $RequestExtend, res: Response, next: $NextFunctionVer) => void { +export default function ( + storage: IStorageHandler +): (req: $RequestExtend, res: Response, next: $NextFunctionVer) => void { const validateInputs = (newUsers, localUsers, username, isStar): boolean => { const isExistlocalUsers = _.isNil(localUsers[username]) === false; if (isStar && isExistlocalUsers && localUsers[username]) { @@ -52,7 +54,10 @@ export default function (storage: IStorageHandler): (req: $RequestExtend, res: R // Check is star or unstar const isStar = Object.keys(newStarUser).includes(remoteUsername); debug('is start? %o', isStar); - if (_.isNil(localStarUsers) === false && validateInputs(newStarUser, localStarUsers, remoteUsername, isStar)) { + if ( + _.isNil(localStarUsers) === false && + validateInputs(newStarUser, localStarUsers, remoteUsername, isStar) + ) { return afterChangePackage(); } const users = isStar diff --git a/packages/api/src/stars.ts b/packages/api/src/stars.ts index 0bb99afa8..a22b5423a 100644 --- a/packages/api/src/stars.ts +++ b/packages/api/src/stars.ts @@ -4,27 +4,33 @@ import { Response, Router } from 'express'; import { USERS, HTTP_STATUS } from '@verdaccio/dev-commons'; import { Package } from '@verdaccio/types'; -import { $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; +import { IStorageHandler } from '@verdaccio/store'; +import { $RequestExtend, $NextFunctionVer } from '../types/custom'; type Packages = Package[]; export default function (route: Router, storage: IStorageHandler): void { - route.get('/-/_view/starredByUser', (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => { - const remoteUsername = req.remote_user.name; + route.get( + '/-/_view/starredByUser', + (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => { + const remoteUsername = req.remote_user.name; - storage.getLocalDatabase((err, localPackages: Packages) => { - if (err) { - return next(err); - } + storage.getLocalDatabase((err, localPackages: Packages) => { + if (err) { + return next(err); + } - const filteredPackages: Packages = localPackages.filter((localPackage: Package) => _.keys(localPackage[USERS]).includes(remoteUsername)); + const filteredPackages: Packages = localPackages.filter((localPackage: Package) => + _.keys(localPackage[USERS]).includes(remoteUsername) + ); - res.status(HTTP_STATUS.OK); - next({ - rows: filteredPackages.map((filteredPackage: Package) => ({ - value: filteredPackage.name, - })), + res.status(HTTP_STATUS.OK); + next({ + rows: filteredPackages.map((filteredPackage: Package) => ({ + value: filteredPackage.name, + })), + }); }); - }); - }); + } + ); } diff --git a/packages/api/src/user.ts b/packages/api/src/user.ts index 8355e4d24..523a55745 100644 --- a/packages/api/src/user.ts +++ b/packages/api/src/user.ts @@ -1,30 +1,50 @@ import _ from 'lodash'; import { Response, Router } from 'express'; -import { createRemoteUser, getAuthenticatedMessage, validatePassword, ErrorCode } from '@verdaccio/utils'; +import { + createRemoteUser, + getAuthenticatedMessage, + validatePassword, + ErrorCode, +} from '@verdaccio/utils'; import { getApiToken } from '@verdaccio/auth'; import { logger } from '@verdaccio/logger'; import { Config, RemoteUser } from '@verdaccio/types'; -import { $RequestExtend, $NextFunctionVer, IAuth } from '@verdaccio/dev-types'; +import { IAuth } from '@verdaccio/auth'; import { API_ERROR, API_MESSAGE, HTTP_STATUS } from '@verdaccio/dev-commons'; +import { $RequestExtend, $NextFunctionVer } from '../types/custom'; export default function (route: Router, auth: IAuth, config: Config): void { - route.get('/-/user/:org_couchdb_user', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.get('/-/user/:org_couchdb_user', function ( + req: $RequestExtend, + res: Response, + next: $NextFunctionVer + ): void { res.status(HTTP_STATUS.OK); next({ ok: getAuthenticatedMessage(req.remote_user.name), }); }); - route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function ( + req: $RequestExtend, + res: Response, + next: $NextFunctionVer + ): void { const { name, password } = req.body; const remoteName = req.remote_user.name; if (_.isNil(remoteName) === false && _.isNil(name) === false && remoteName === name) { - auth.authenticate(name, password, async function callbackAuthenticate(err, user): Promise { + auth.authenticate(name, password, async function callbackAuthenticate( + err, + user + ): Promise { if (err) { - logger.trace({ name, err }, 'authenticating for user @{username} failed. Error: @{err.message}'); + logger.trace( + { name, err }, + 'authenticating for user @{username} failed. Error: @{err.message}' + ); return next(ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD)); } @@ -50,12 +70,15 @@ export default function (route: Router, auth: IAuth, config: Config): void { // 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( + ErrorCode.getCode(err.status, err.message) || ErrorCode.getConflict(err.message) + ); } return next(err); } - const token = name && password ? await getApiToken(auth, config, user, password) : undefined; + const token = + name && password ? await getApiToken(auth, config, user, password) : undefined; req.remote_user = user; res.status(HTTP_STATUS.CREATED); @@ -67,7 +90,11 @@ export default function (route: Router, auth: IAuth, config: Config): void { } }); - route.delete('/-/user/token/*', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.delete('/-/user/token/*', function ( + req: $RequestExtend, + res: Response, + next: $NextFunctionVer + ): void { res.status(HTTP_STATUS.OK); next({ ok: API_MESSAGE.LOGGED_OUT, diff --git a/packages/api/src/v1/profile.ts b/packages/api/src/v1/profile.ts index 04bc124c9..0846eb57d 100644 --- a/packages/api/src/v1/profile.ts +++ b/packages/api/src/v1/profile.ts @@ -3,7 +3,8 @@ import { Response, Router } from 'express'; import { API_ERROR, APP_ERROR, HTTP_STATUS, SUPPORT_ERRORS } from '@verdaccio/dev-commons'; import { ErrorCode, validatePassword } from '@verdaccio/utils'; -import { $NextFunctionVer, $RequestExtend, IAuth } from '@verdaccio/dev-types'; +import { IAuth } from '@verdaccio/auth'; +import { $RequestExtend, $NextFunctionVer } from '../../types/custom'; export interface Profile { tfa: boolean; @@ -30,7 +31,11 @@ export default function (route: Router, auth: IAuth): void { }; } - route.get('/-/npm/v1/user', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.get('/-/npm/v1/user', function ( + req: $RequestExtend, + res: Response, + next: $NextFunctionVer + ): void { if (_.isNil(req.remote_user.name) === false) { return next(buildProfile(req.remote_user.name)); } @@ -41,7 +46,11 @@ export default function (route: Router, auth: IAuth): void { }); }); - route.post('/-/npm/v1/user', function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void { + route.post('/-/npm/v1/user', function ( + req: $RequestExtend, + res: Response, + next: $NextFunctionVer + ): void { if (_.isNil(req.remote_user.name)) { res.status(HTTP_STATUS.UNAUTHORIZED); return next({ @@ -65,7 +74,9 @@ export default function (route: Router, auth: IAuth): void { password.new, (err, isUpdated): $NextFunctionVer => { if (_.isNull(err) === false) { - return next(ErrorCode.getCode(err.status, err.message) || ErrorCode.getConflict(err.message)); + return next( + ErrorCode.getCode(err.status, err.message) || ErrorCode.getConflict(err.message) + ); } if (isUpdated) { diff --git a/packages/api/src/v1/search.ts b/packages/api/src/v1/search.ts index 0466f46b9..6ebfb331a 100644 --- a/packages/api/src/v1/search.ts +++ b/packages/api/src/v1/search.ts @@ -40,9 +40,11 @@ function compileTextSearch(textSearch: string): (pkg: Package) => boolean { export default function (route, auth, storage): void { route.get('/-/v1/search', (req, res) => { // TODO: implement proper result scoring weighted by quality, popularity and maintenance query parameters - let [text, size, from /* , quality, popularity, maintenance */] = ['text', 'size', 'from' /* , 'quality', 'popularity', 'maintenance' */].map( - (k) => req.query[k] - ); + let [text, size, from /* , quality, popularity, maintenance */] = [ + 'text', + 'size', + 'from' /* , 'quality', 'popularity', 'maintenance' */, + ].map((k) => req.query[k]); size = parseInt(size) || 20; from = parseInt(from) || 0; @@ -61,7 +63,9 @@ export default function (route, auth, storage): void { return { package: pkg, flags: { - unstable: Object.keys(pkg.versions).some((v) => semver.satisfies(v, '^1.0.0')) ? undefined : true, + unstable: Object.keys(pkg.versions).some((v) => semver.satisfies(v, '^1.0.0')) + ? undefined + : true, }, score: { final: 1, diff --git a/packages/api/src/v1/token.ts b/packages/api/src/v1/token.ts index 03dd7b58a..abdbd3790 100644 --- a/packages/api/src/v1/token.ts +++ b/packages/api/src/v1/token.ts @@ -6,7 +6,9 @@ import { logger } from '@verdaccio/logger'; import { Response, Router } from 'express'; import { Config, RemoteUser, Token } from '@verdaccio/types'; -import { $NextFunctionVer, $RequestExtend, IAuth, IStorageHandler } from '../../../types'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; +import { $RequestExtend, $NextFunctionVer } from '../../types/custom'; export type NormalizeToken = Token & { created: string; @@ -20,8 +22,17 @@ function normalizeToken(token: Token): NormalizeToken { } // https://github.com/npm/npm-profile/blob/latest/lib/index.js -export default function (route: Router, auth: IAuth, storage: IStorageHandler, config: Config): void { - route.get('/-/npm/v1/tokens', async function (req: $RequestExtend, res: Response, next: $NextFunctionVer) { +export default function ( + route: Router, + auth: IAuth, + storage: IStorageHandler, + config: Config +): void { + route.get('/-/npm/v1/tokens', async function ( + req: $RequestExtend, + res: Response, + next: $NextFunctionVer + ) { const { name } = req.remote_user; if (_.isNil(name) === false) { @@ -45,7 +56,11 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c return next(ErrorCode.getUnauthorized()); }); - route.post('/-/npm/v1/tokens', function (req: $RequestExtend, res: Response, next: $NextFunctionVer) { + route.post('/-/npm/v1/tokens', function ( + req: $RequestExtend, + res: Response, + next: $NextFunctionVer + ) { const { password, readonly, cidr_whitelist } = req.body; const { name } = req.remote_user; @@ -62,7 +77,9 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c req.remote_user = user; if (!_.isFunction(storage.saveToken)) { - return next(ErrorCode.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)); + return next( + ErrorCode.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT) + ); } try { @@ -104,23 +121,26 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler, c }); }); - route.delete('/-/npm/v1/tokens/token/:tokenKey', async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => { - const { - params: { tokenKey }, - } = req; - const { name } = req.remote_user; + route.delete( + '/-/npm/v1/tokens/token/:tokenKey', + async (req: $RequestExtend, res: Response, next: $NextFunctionVer) => { + const { + params: { tokenKey }, + } = req; + const { name } = req.remote_user; - if (_.isNil(name) === false) { - logger.debug({ name }, '@{name} has requested remove a token'); - try { - await storage.deleteToken(name, tokenKey); - logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}'); - return next({}); - } catch (error) { - logger.error({ error: error.msg }, 'token creation has failed: @{error}'); - return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); + if (_.isNil(name) === false) { + logger.debug({ name }, '@{name} has requested remove a token'); + try { + await storage.deleteToken(name, tokenKey); + logger.info({ tokenKey, name }, 'token id @{tokenKey} was revoked for user @{name}'); + return next({}); + } catch (error) { + logger.error({ error: error.msg }, 'token creation has failed: @{error}'); + return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message)); + } } + return next(ErrorCode.getUnauthorized()); } - return next(ErrorCode.getUnauthorized()); - }); + ); } diff --git a/packages/api/src/whoami.ts b/packages/api/src/whoami.ts index 14fd804e7..c6d22e8b3 100644 --- a/packages/api/src/whoami.ts +++ b/packages/api/src/whoami.ts @@ -1,5 +1,5 @@ import { Response, Router } from 'express'; -import { $RequestExtend, $NextFunctionVer } from '@verdaccio/dev-types'; +import { $RequestExtend, $NextFunctionVer } from '../types/custom'; export default function (route: Router): void { route.get('/whoami', (req: $RequestExtend, res: Response, next: $NextFunctionVer): void => { diff --git a/packages/api/test/integration/_helper.ts b/packages/api/test/integration/_helper.ts index 12c4a4d5a..2b609ef20 100644 --- a/packages/api/test/integration/_helper.ts +++ b/packages/api/test/integration/_helper.ts @@ -7,8 +7,7 @@ import { parseConfigFile } from '@verdaccio/utils'; import { Config } from '@verdaccio/config'; import { Storage } from '@verdaccio/store'; import { final, handleError, errorReportingMiddleware } from '@verdaccio/middleware'; -import { Auth } from '@verdaccio/auth'; -import { IAuth } from '@verdaccio/dev-types'; +import { Auth, IAuth } from '@verdaccio/auth'; import { HEADER_TYPE, HTTP_STATUS, generatePackageMetadata } from '@verdaccio/dev-commons'; import { HEADERS } from '@verdaccio/commons-api'; import apiEndpoints from '../../src'; @@ -56,13 +55,23 @@ export function publishVersion(app, configFile, pkgName, version): supertest.Tes .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); } -export async function publishTaggedVersion(app, configFile, pkgName: string, version: string, tag: string) { +export async function publishTaggedVersion( + app, + configFile, + pkgName: string, + version: string, + tag: string +) { const pkgMetadata = generatePackageMetadata(pkgName, version, { [tag]: version, }); return supertest(app) - .put(`/${encodeURIComponent(pkgName)}/${encodeURIComponent(version)}/-tag/${encodeURIComponent(tag)}`) + .put( + `/${encodeURIComponent(pkgName)}/${encodeURIComponent(version)}/-tag/${encodeURIComponent( + tag + )}` + ) .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) .send(JSON.stringify(pkgMetadata)) .expect(HTTP_STATUS.CREATED) diff --git a/packages/api/test/integration/package.spec.ts b/packages/api/test/integration/package.spec.ts index 7d6cd692b..74f9b8299 100644 --- a/packages/api/test/integration/package.spec.ts +++ b/packages/api/test/integration/package.spec.ts @@ -2,13 +2,15 @@ import supertest from 'supertest'; import { HTTP_STATUS } from '@verdaccio/commons-api'; import { HEADER_TYPE, HEADERS } from '@verdaccio/dev-commons'; -import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; +import { $ResponseExtend, $RequestExtend } from '../../types/custom'; import { initializeServer, publishTaggedVersion, publishVersion } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'foo', groups: [], real_groups: [] }; - _next(); -}); +const mockApiJWTmiddleware = jest.fn( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'foo', groups: [], real_groups: [] }; + _next(); + } +); jest.mock('@verdaccio/auth', () => ({ Auth: class { diff --git a/packages/api/test/integration/publish.spec.ts b/packages/api/test/integration/publish.spec.ts index 52051ed07..cdf7fb47c 100644 --- a/packages/api/test/integration/publish.spec.ts +++ b/packages/api/test/integration/publish.spec.ts @@ -1,13 +1,21 @@ import { HTTP_STATUS } from '@verdaccio/commons-api'; -import { API_ERROR, API_MESSAGE, generatePackageMetadata, HEADER_TYPE, HEADERS } from '@verdaccio/dev-commons'; -import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; import supertest from 'supertest'; +import { + API_ERROR, + API_MESSAGE, + generatePackageMetadata, + HEADER_TYPE, + HEADERS, +} from '@verdaccio/dev-commons'; +import { $ResponseExtend, $RequestExtend } from '../../types/custom'; import { initializeServer, publishVersion } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'foo', groups: [], real_groups: [] }; - _next(); -}); +const mockApiJWTmiddleware = jest.fn( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'foo', groups: [], real_groups: [] }; + _next(); + } +); jest.setTimeout(50000000); diff --git a/packages/api/test/integration/user.spec.ts b/packages/api/test/integration/user.spec.ts index 60c9d84e6..c0fe97810 100644 --- a/packages/api/test/integration/user.spec.ts +++ b/packages/api/test/integration/user.spec.ts @@ -1,16 +1,18 @@ import supertest from 'supertest'; +import _ from 'lodash'; import { HTTP_STATUS, API_ERROR } from '@verdaccio/commons-api'; import { HEADERS, HEADER_TYPE, API_MESSAGE } from '@verdaccio/dev-commons'; -import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; import { getBadRequest, getConflict, getUnauthorized } from '@verdaccio/commons-api'; -import _ from 'lodash'; +import { $RequestExtend, $ResponseExtend } from '../../types/custom'; import { initializeServer } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'test', groups: [], real_groups: [] }; - _next(); -}); +const mockApiJWTmiddleware = jest.fn( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'test', groups: [], real_groups: [] }; + _next(); + } +); const mockAuthenticate = jest.fn(() => (_name, _password, callback): void => { return callback(null, ['all']); @@ -42,10 +44,12 @@ describe('user', () => { const credentials = { name: 'test', password: 'test' }; test('should test add a new user', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined }; - _next(); - }); + mockApiJWTmiddleware.mockImplementationOnce( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + } + ); mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { return callback(null, true); @@ -72,10 +76,12 @@ describe('user', () => { }); test('should test fails on add a existing user with login', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined }; - _next(); - }); + mockApiJWTmiddleware.mockImplementationOnce( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + } + ); supertest(await initializeServer('user.yaml')) .put('/-/user/org.couchdb.user:jotaNew') .send(credentials) @@ -109,10 +115,12 @@ describe('user', () => { }); test('should test fails add a new user with missing name', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined }; - _next(); - }); + mockApiJWTmiddleware.mockImplementationOnce( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + } + ); mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => { return callback(getBadRequest(API_ERROR.USERNAME_PASSWORD_REQUIRED)); }); @@ -136,10 +144,12 @@ describe('user', () => { }); test('should test fails add a new user with missing password', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: undefined }; - _next(); - }); + mockApiJWTmiddleware.mockImplementationOnce( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: undefined }; + _next(); + } + ); const credentialsShort = _.cloneDeep(credentials); delete credentialsShort.password; @@ -162,10 +172,12 @@ describe('user', () => { }); test('should test fails add a new user with wrong password', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'test' }; - _next(); - }); + mockApiJWTmiddleware.mockImplementationOnce( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'test' }; + _next(); + } + ); mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); }); @@ -189,10 +201,12 @@ describe('user', () => { }); test('should be able to logout an user', async (done) => { - mockApiJWTmiddleware.mockImplementationOnce(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'test' }; - _next(); - }); + mockApiJWTmiddleware.mockImplementationOnce( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'test' }; + _next(); + } + ); mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => { return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD)); }); diff --git a/packages/api/test/integration/whoami.spec.ts b/packages/api/test/integration/whoami.spec.ts index 2f01d08fb..6b876fc40 100644 --- a/packages/api/test/integration/whoami.spec.ts +++ b/packages/api/test/integration/whoami.spec.ts @@ -2,13 +2,16 @@ import supertest from 'supertest'; import { HTTP_STATUS } from '@verdaccio/commons-api'; import { HEADERS } from '@verdaccio/dev-commons'; -import { $RequestExtend, $ResponseExtend } from '@verdaccio/dev-types'; + +import { $RequestExtend, $ResponseExtend } from '../../types/custom'; import { initializeServer } from './_helper'; -const mockApiJWTmiddleware = jest.fn(() => (req: $RequestExtend, res: $ResponseExtend, _next): void => { - req.remote_user = { name: 'foo', groups: [], real_groups: [] }; - _next(); -}); +const mockApiJWTmiddleware = jest.fn( + () => (req: $RequestExtend, res: $ResponseExtend, _next): void => { + req.remote_user = { name: 'foo', groups: [], real_groups: [] }; + _next(); + } +); jest.mock('@verdaccio/auth', () => ({ Auth: class { diff --git a/packages/api/test/unit/publish.spec.ts b/packages/api/test/unit/publish.spec.ts index 113fb1a07..8da32c437 100644 --- a/packages/api/test/unit/publish.spec.ts +++ b/packages/api/test/unit/publish.spec.ts @@ -1,5 +1,11 @@ import { HTTP_STATUS, API_ERROR } from '@verdaccio/dev-commons'; -import { addVersion, uploadPackageTarball, removeTarball, unPublishPackage, publishPackage } from '../../src/publish'; +import { + addVersion, + uploadPackageTarball, + removeTarball, + unPublishPackage, + publishPackage, +} from '../../src/publish'; const REVISION_MOCK = '15-e53a77096b0ee33e'; diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index 0f4253dfb..a0158a0f2 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -22,9 +22,6 @@ { "path": "../store" }, - { - "path": "../types" - }, { "path": "../middleware" }, diff --git a/packages/api/types/custom.d.ts b/packages/api/types/custom.d.ts index dfc4ffcdd..72cee6d7d 100644 --- a/packages/api/types/custom.d.ts +++ b/packages/api/types/custom.d.ts @@ -1,4 +1,9 @@ import { Logger, RemoteUser } from '@verdaccio/types'; +import { NextFunction, Request, Response } from 'express'; + +export type $RequestExtend = Request & { remote_user?: any; log: Logger }; +export type $ResponseExtend = Response & { cookies?: any }; +export type $NextFunctionVer = NextFunction & any; declare global { namespace Express { diff --git a/packages/auth/package.json b/packages/auth/package.json index 17ee801e9..5bf2d8e2e 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -34,7 +34,6 @@ }, "devDependencies": { "@verdaccio/config": "workspace:5.0.0-alpha.0", - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/mock": "workspace:5.0.0-alpha.0", "@verdaccio/types": "workspace:*" }, diff --git a/packages/auth/src/auth.ts b/packages/auth/src/auth.ts index 7d62638c2..88968673a 100644 --- a/packages/auth/src/auth.ts +++ b/packages/auth/src/auth.ts @@ -1,8 +1,13 @@ import _ from 'lodash'; -import { NextFunction } from 'express'; +import { NextFunction, Request, Response } from 'express'; import buildDebug from 'debug'; -import { VerdaccioError, getBadRequest, getInternalError, getForbidden } from '@verdaccio/commons-api'; +import { + VerdaccioError, + getBadRequest, + getInternalError, + getForbidden, +} from '@verdaccio/commons-api'; import { API_ERROR, SUPPORT_ERRORS, TOKEN_BASIC, TOKEN_BEARER } from '@verdaccio/dev-commons'; import { loadPlugin } from '@verdaccio/loaders'; import { @@ -17,15 +22,62 @@ import { createRemoteUser, } from '@verdaccio/utils'; -import { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security, AuthPluginPackage, AllowAccess, PackageAccess } from '@verdaccio/types'; -import { $RequestExtend, $ResponseExtend, IAuth, AESPayload } from '@verdaccio/dev-types'; -import { getMiddlewareCredentials, getSecurity, verifyJWTPayload, parseBasicPayload, parseAuthTokenHeader, isAuthHeaderValid, isAESLegacy } from './utils'; +import { + Config, + Logger, + Callback, + IPluginAuth, + RemoteUser, + IBasicAuth, + JWTSignOptions, + Security, + AuthPluginPackage, + AllowAccess, + PackageAccess, +} from '@verdaccio/types'; +import { + getMiddlewareCredentials, + getSecurity, + verifyJWTPayload, + parseBasicPayload, + parseAuthTokenHeader, + isAuthHeaderValid, + isAESLegacy, +} from './utils'; /* eslint-disable @typescript-eslint/no-var-requires */ const LoggerApi = require('@verdaccio/logger'); const debug = buildDebug('verdaccio:auth'); +export interface IAuthWebUI { + jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise; + aesEncrypt(buf: Buffer): Buffer; +} + +export interface AESPayload { + user: string; + password: string; +} + +export type $RequestExtend = Request & { remote_user?: any; log: Logger }; +export type $ResponseExtend = Response & { cookies?: any }; +export type $NextFunctionVer = NextFunction & any; + +export interface IAuthMiddleware { + apiJWTmiddleware(): $NextFunctionVer; + webUIJWTmiddleware(): $NextFunctionVer; +} + +export interface IAuth extends IBasicAuth, IAuthMiddleware, IAuthWebUI { + config: Config; + logger: Logger; + secret: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + plugins: any[]; + allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void; +} + class Auth implements IAuth { public config: Config; public logger: Logger; @@ -46,19 +98,29 @@ class Auth implements IAuth { logger: this.logger, }; - return loadPlugin>(config, config.auth, pluginOptions, (plugin: IPluginAuth): boolean => { - const { authenticate, allow_access, allow_publish } = plugin; + return loadPlugin>( + config, + config.auth, + pluginOptions, + (plugin: IPluginAuth): boolean => { + const { authenticate, allow_access, allow_publish } = plugin; - // @ts-ignore - return authenticate || allow_access || allow_publish; - }); + // @ts-ignore + return authenticate || allow_access || allow_publish; + } + ); } private _applyDefaultPlugins(): void { this.plugins.push(getDefaultPlugins(this.logger)); } - public changePassword(username: string, password: string, newPassword: string, cb: Callback): void { + public changePassword( + username: string, + password: string, + newPassword: string, + cb: Callback + ): void { const validPlugins = _.filter(this.plugins, (plugin) => isFunction(plugin.changePassword)); if (_.isEmpty(validPlugins)) { @@ -140,7 +202,9 @@ class Auth implements IAuth { let method = 'adduser'; if (isFunction(plugin[method]) === false) { method = 'add_user'; - self.logger.warn('the plugin method add_user in the auth plugin is deprecated and will be removed in next major release, notify to the plugin author'); + self.logger.warn( + 'the plugin method add_user in the auth plugin is deprecated and will be removed in next major release, notify to the plugin author' + ); } if (isFunction(plugin[method]) === false) { @@ -165,10 +229,18 @@ class Auth implements IAuth { /** * Allow user to access a package. */ - public allow_access({ packageName, packageVersion }: AuthPluginPackage, user: RemoteUser, callback: Callback): void { + public allow_access( + { packageName, packageVersion }: AuthPluginPackage, + user: RemoteUser, + callback: Callback + ): void { const plugins = this.plugins.slice(0); const pkgAllowAcces: AllowAccess = { name: packageName, version: packageVersion }; - const pkg = Object.assign({}, pkgAllowAcces, getMatchedPackagesSpec(packageName, this.config.packages)) as AllowAccess & PackageAccess; + const pkg = Object.assign( + {}, + pkgAllowAcces, + getMatchedPackagesSpec(packageName, this.config.packages) + ) as AllowAccess & PackageAccess; const self = this; debug('allow access for %o', packageName); @@ -195,8 +267,15 @@ class Auth implements IAuth { })(); } - public allow_unpublish({ packageName, packageVersion }: AuthPluginPackage, user: RemoteUser, callback: Callback): void { - const pkg = Object.assign({ name: packageName, version: packageVersion }, getMatchedPackagesSpec(packageName, this.config.packages)); + public allow_unpublish( + { packageName, packageVersion }: AuthPluginPackage, + user: RemoteUser, + callback: Callback + ): void { + const pkg = Object.assign( + { name: packageName, version: packageVersion }, + getMatchedPackagesSpec(packageName, this.config.packages) + ); debug('allow unpublish for %o', packageName); for (const plugin of this.plugins) { @@ -206,7 +285,10 @@ class Auth implements IAuth { } else { plugin.allow_unpublish!(user, pkg, (err, ok: boolean): void => { if (err) { - debug('forbidden publish for %o, it will fallback on unpublish permissions', packageName); + debug( + 'forbidden publish for %o, it will fallback on unpublish permissions', + packageName + ); return callback(err); } @@ -229,10 +311,17 @@ class Auth implements IAuth { /** * Allow user to publish a package. */ - public allow_publish({ packageName, packageVersion }: AuthPluginPackage, user: RemoteUser, callback: Callback): void { + public allow_publish( + { packageName, packageVersion }: AuthPluginPackage, + user: RemoteUser, + callback: Callback + ): void { const plugins = this.plugins.slice(0); const self = this; - const pkg = Object.assign({ name: packageName, version: packageVersion }, getMatchedPackagesSpec(packageName, this.config.packages)); + const pkg = Object.assign( + { name: packageName, version: packageVersion }, + getMatchedPackagesSpec(packageName, this.config.packages) + ); debug('allow publish for %o init | plugins: %o', packageName, plugins.length); (function next(): void { @@ -320,7 +409,13 @@ class Auth implements IAuth { }; } - private _handleJWTAPIMiddleware(req: $RequestExtend, security: Security, secret: string, authorization: string, next: Function): void { + private _handleJWTAPIMiddleware( + req: $RequestExtend, + security: Security, + secret: string, + authorization: string, + next: Function + ): void { const { scheme, token } = parseAuthTokenHeader(authorization); if (scheme.toUpperCase() === TOKEN_BASIC.toUpperCase()) { // this should happen when client tries to login with an existing user @@ -349,7 +444,13 @@ class Auth implements IAuth { } } - private _handleAESMiddleware(req: $RequestExtend, security: Security, secret: string, authorization: string, next: Function): void { + private _handleAESMiddleware( + req: $RequestExtend, + security: Security, + secret: string, + authorization: string, + next: Function + ): void { const credentials: any = getMiddlewareCredentials(security, secret, authorization); if (credentials) { const { user, password } = credentials; diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index 308a3becf..bc1527464 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -1,2 +1,2 @@ -export { Auth } from './auth'; +export { Auth, IAuth, IAuthWebUI } from './auth'; export * from './utils'; diff --git a/packages/auth/src/utils.ts b/packages/auth/src/utils.ts index ef6c1bf9d..ac7b510d5 100644 --- a/packages/auth/src/utils.ts +++ b/packages/auth/src/utils.ts @@ -1,8 +1,25 @@ -import { Config, RemoteUser, Security } from '@verdaccio/types'; -import { AuthMiddlewarePayload, AuthTokenHeader, BasicPayload, IAuthWebUI } from '@verdaccio/dev-types'; import _ from 'lodash'; +import { Config, RemoteUser, Security } from '@verdaccio/types'; import { HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '@verdaccio/dev-commons'; -import { aesDecrypt, buildUserBuffer, convertPayloadToBase64, createAnonymousRemoteUser, defaultSecurity, ErrorCode, verifyPayload } from '@verdaccio/utils'; +import { + aesDecrypt, + buildUserBuffer, + convertPayloadToBase64, + createAnonymousRemoteUser, + defaultSecurity, + ErrorCode, + verifyPayload, +} from '@verdaccio/utils'; + +import { IAuthWebUI, AESPayload } from './auth'; + +export type BasicPayload = AESPayload | void; +export type AuthMiddlewarePayload = RemoteUser | BasicPayload; + +export interface AuthTokenHeader { + scheme: string; + token: string; +} export function parseAuthTokenHeader(authorizationHeader: string): AuthTokenHeader { const parts = authorizationHeader.split(' '); @@ -27,7 +44,11 @@ export function parseAESCredentials(authorizationHeader: string, secret: string) } } -export function getMiddlewareCredentials(security: Security, secret: string, authorizationHeader: string): AuthMiddlewarePayload { +export function getMiddlewareCredentials( + security: Security, + secret: string, + authorizationHeader: string +): AuthMiddlewarePayload { if (isAESLegacy(security)) { const credentials = parseAESCredentials(authorizationHeader, secret); if (!credentials) { @@ -54,13 +75,20 @@ export function isAESLegacy(security: Security): boolean { return _.isNil(legacy) === false && _.isNil(jwt) && legacy === true; } -export async function getApiToken(auth: IAuthWebUI, config: Config, remoteUser: RemoteUser, aesPassword: string): Promise { +export async function getApiToken( + auth: IAuthWebUI, + config: Config, + remoteUser: RemoteUser, + aesPassword: string +): Promise { const security: Security = getSecurity(config); if (isAESLegacy(security)) { // fallback all goes to AES encryption return await new Promise((resolve): void => { - resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64')); + resolve( + auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64') + ); }); } // i am wiling to use here _.isNil but flow does not like it yet. @@ -70,7 +98,9 @@ export async function getApiToken(auth: IAuthWebUI, config: Config, remoteUser: return await auth.jwtEncrypt(remoteUser, jwt.sign); } return await new Promise((resolve): void => { - resolve(auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64')); + resolve( + auth.aesEncrypt(buildUserBuffer(remoteUser.name as string, aesPassword)).toString('base64') + ); }); } diff --git a/packages/auth/test/auth-utils.spec.ts b/packages/auth/test/auth-utils.spec.ts index aba2a7eb0..582812751 100644 --- a/packages/auth/test/auth-utils.spec.ts +++ b/packages/auth/test/auth-utils.spec.ts @@ -19,9 +19,8 @@ import { signPayload, } from '@verdaccio/utils'; -import { IAuth } from '@verdaccio/dev-types'; import { Config, Security, RemoteUser } from '@verdaccio/types'; -import { Auth } from '../src'; +import { Auth, IAuth } from '../src'; import { getMiddlewareCredentials, getApiToken, verifyJWTPayload, getSecurity } from '../src'; setup([]); @@ -86,7 +85,9 @@ describe('Auth utilities', () => { }; const verifyAES = (token: string, user: string, password: string, secret: string) => { - const payload = aesDecrypt(convertPayloadToBase64(token), secret).toString(CHARACTER_ENCODING.UTF8); + const payload = aesDecrypt(convertPayloadToBase64(token), secret).toString( + CHARACTER_ENCODING.UTF8 + ); const content = payload.split(':'); expect(content[0]).toBe(user); @@ -95,49 +96,98 @@ describe('Auth utilities', () => { describe('getApiToken test', () => { test('should sign token with aes and security missing', async () => { - const token = await signCredentials('security-missing', 'test', 'test', '1234567', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials( + 'security-missing', + 'test', + 'test', + '1234567', + 'aesEncrypt', + 'jwtEncrypt' + ); verifyAES(token, 'test', 'test', '1234567'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with aes and security empty', async () => { - const token = await signCredentials('security-empty', 'test', 'test', '123456', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials( + 'security-empty', + 'test', + 'test', + '123456', + 'aesEncrypt', + 'jwtEncrypt' + ); verifyAES(token, 'test', 'test', '123456'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with aes', async () => { - const token = await signCredentials('security-basic', 'test', 'test', '123456', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials( + 'security-basic', + 'test', + 'test', + '123456', + 'aesEncrypt', + 'jwtEncrypt' + ); verifyAES(token, 'test', 'test', '123456'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with legacy and jwt disabled', async () => { - const token = await signCredentials('security-no-legacy', 'test', 'test', 'x8T#ZCx=2t', 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials( + 'security-no-legacy', + 'test', + 'test', + 'x8T#ZCx=2t', + 'aesEncrypt', + 'jwtEncrypt' + ); expect(_.isString(token)).toBeTruthy(); verifyAES(token, 'test', 'test', 'x8T#ZCx=2t'); }); test('should sign token with legacy enabled and jwt enabled', async () => { - const token = await signCredentials('security-jwt-legacy-enabled', 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials( + 'security-jwt-legacy-enabled', + 'test', + 'test', + 'secret', + 'jwtEncrypt', + 'aesEncrypt' + ); verifyJWT(token, 'test', 'test', 'secret'); expect(_.isString(token)).toBeTruthy(); }); test('should sign token with jwt enabled', async () => { - const token = await signCredentials('security-jwt', 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials( + 'security-jwt', + 'test', + 'test', + 'secret', + 'jwtEncrypt', + 'aesEncrypt' + ); expect(_.isString(token)).toBeTruthy(); verifyJWT(token, 'test', 'test', 'secret'); }); test('should sign with jwt whether legacy is disabled', async () => { - const token = await signCredentials('security-legacy-disabled', 'test', 'test', 'secret', 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials( + 'security-legacy-disabled', + 'test', + 'test', + 'secret', + 'jwtEncrypt', + 'aesEncrypt' + ); expect(_.isString(token)).toBeTruthy(); verifyJWT(token, 'test', 'test', 'secret'); @@ -156,7 +206,14 @@ describe('Auth utilities', () => { const secret = 'secret'; const user = 'test'; const pass = 'test'; - const token = await signCredentials('security-legacy', user, pass, secret, 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials( + 'security-legacy', + user, + pass, + secret, + 'aesEncrypt', + 'jwtEncrypt' + ); const config: Config = getConfig('security-legacy', secret); const security: Security = getSecurity(config); const credentials = getMiddlewareCredentials(security, secret, `Bearer ${token}`); @@ -184,19 +241,41 @@ describe('Auth utilities', () => { test.concurrent('should return empty credential wrong secret key', async () => { const secret = 'secret'; - const token = await signCredentials('security-legacy', 'test', 'test', secret, 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials( + 'security-legacy', + 'test', + 'test', + secret, + 'aesEncrypt', + 'jwtEncrypt' + ); const config: Config = getConfig('security-legacy', secret); const security: Security = getSecurity(config); - const credentials = getMiddlewareCredentials(security, 'BAD_SECRET', buildToken(TOKEN_BEARER, token)); + const credentials = getMiddlewareCredentials( + security, + 'BAD_SECRET', + buildToken(TOKEN_BEARER, token) + ); expect(credentials).not.toBeDefined(); }); test.concurrent('should return empty credential wrong scheme', async () => { const secret = 'secret'; - const token = await signCredentials('security-legacy', 'test', 'test', secret, 'aesEncrypt', 'jwtEncrypt'); + const token = await signCredentials( + 'security-legacy', + 'test', + 'test', + secret, + 'aesEncrypt', + 'jwtEncrypt' + ); const config: Config = getConfig('security-legacy', secret); const security: Security = getSecurity(config); - const credentials = getMiddlewareCredentials(security, secret, buildToken('BAD_SCHEME', token)); + const credentials = getMiddlewareCredentials( + security, + secret, + buildToken('BAD_SCHEME', token) + ); expect(credentials).not.toBeDefined(); }); @@ -206,7 +285,11 @@ describe('Auth utilities', () => { const auth: IAuth = new Auth(config); const token = auth.aesEncrypt(Buffer.from(`corruptedBuffer`)).toString('base64'); const security: Security = getSecurity(config); - const credentials = getMiddlewareCredentials(security, secret, buildToken(TOKEN_BEARER, token)); + const credentials = getMiddlewareCredentials( + security, + secret, + buildToken(TOKEN_BEARER, token) + ); expect(credentials).not.toBeDefined(); }); }); @@ -229,7 +312,11 @@ describe('Auth utilities', () => { test('should return anonymous whether token is corrupted', () => { const config: Config = getConfig('security-jwt', '12345'); const security: Security = getSecurity(config); - const credentials = getMiddlewareCredentials(security, '12345', buildToken(TOKEN_BEARER, 'fakeToken')); + const credentials = getMiddlewareCredentials( + security, + '12345', + buildToken(TOKEN_BEARER, 'fakeToken') + ); expect(credentials).toBeDefined(); // @ts-ignore @@ -243,7 +330,11 @@ describe('Auth utilities', () => { test('should return anonymous whether token and scheme are corrupted', () => { const config: Config = getConfig('security-jwt', '12345'); const security: Security = getSecurity(config); - const credentials = getMiddlewareCredentials(security, '12345', buildToken('FakeScheme', 'fakeToken')); + const credentials = getMiddlewareCredentials( + security, + '12345', + buildToken('FakeScheme', 'fakeToken') + ); expect(credentials).not.toBeDefined(); }); @@ -252,9 +343,20 @@ describe('Auth utilities', () => { const secret = 'secret'; const user = 'test'; const config: Config = getConfig('security-jwt', secret); - const token = await signCredentials('security-jwt', user, 'secretTest', secret, 'jwtEncrypt', 'aesEncrypt'); + const token = await signCredentials( + 'security-jwt', + user, + 'secretTest', + secret, + 'jwtEncrypt', + 'aesEncrypt' + ); const security: Security = getSecurity(config); - const credentials = getMiddlewareCredentials(security, secret, buildToken(TOKEN_BEARER, token)); + const credentials = getMiddlewareCredentials( + security, + secret, + buildToken(TOKEN_BEARER, token) + ); expect(credentials).toBeDefined(); // @ts-ignore expect(credentials.name).toEqual(user); diff --git a/packages/auth/test/auth.spec.ts b/packages/auth/test/auth.spec.ts index bc6a97358..9e28c1ac6 100644 --- a/packages/auth/test/auth.spec.ts +++ b/packages/auth/test/auth.spec.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import { Config as AppConfig } from '@verdaccio/config'; import { setup } from '@verdaccio/logger'; -import { IAuth } from '@verdaccio/dev-types'; +import { IAuth } from '@verdaccio/auth'; import { Config } from '@verdaccio/types'; import { ROLES } from '@verdaccio/dev-commons'; import { getInternalError } from '@verdaccio/commons-api'; @@ -35,7 +35,14 @@ describe('AuthTest', () => { expect(callback).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledWith(null, { - groups: ['test', ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL], + groups: [ + 'test', + ROLES.$ALL, + ROLES.$AUTH, + ROLES.DEPRECATED_ALL, + ROLES.DEPRECATED_AUTH, + ROLES.ALL, + ], name: 'foo', real_groups: groups, }); diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 6b9c40e18..5e85a89b3 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -13,11 +13,19 @@ import { isVersionValid, MIN_NODE_VERSION } from './utils'; const isRootUser = process.getuid && process.getuid() === 0; if (isRootUser) { - global.console.warn(bgYellow().red("*** WARNING: Verdaccio doesn't need superuser privileges. Don't run it under root! ***")); + global.console.warn( + bgYellow().red( + "*** WARNING: Verdaccio doesn't need superuser privileges. Don't run it under root! ***" + ) + ); } if (isVersionValid()) { - global.console.error(bgRed(`Verdaccio requires at least Node.js ${MIN_NODE_VERSION} or higher, please upgrade your Node.js distribution`)); + global.console.error( + bgRed( + `Verdaccio requires at least Node.js ${MIN_NODE_VERSION} or higher, please upgrade your Node.js distribution` + ) + ); process.exit(1); } diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 95159ecdf..f0c8accb4 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -36,7 +36,14 @@ export default function initProgram(commander, pkgVersion, pkgName) { // initLogger.warn({file: configPathLocation}, 'config file - @{file}'); - startVerdaccio(verdaccioConfiguration, cliListener, configPathLocation, pkgVersion, pkgName, listenDefaultCallback); + startVerdaccio( + verdaccioConfiguration, + cliListener, + configPathLocation, + pkgVersion, + pkgName, + listenDefaultCallback + ); } catch (err) { // initLogger.fatal({file: configPathLocation, err: err}, 'cannot open config file @{file}: @{!err.message}'); process.exit(1); diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts index 86ea71db9..57d5af803 100644 --- a/packages/cli/src/utils.ts +++ b/packages/cli/src/utils.ts @@ -2,4 +2,5 @@ import semver from 'semver'; export const MIN_NODE_VERSION = '6.9.0'; -export const isVersionValid = () => semver.satisfies(process.version, `>=${MIN_NODE_VERSION}`) === false; +export const isVersionValid = () => + semver.satisfies(process.version, `>=${MIN_NODE_VERSION}`) === false; diff --git a/packages/commons/src/constants.ts b/packages/commons/src/constants.ts index 645e2393d..3fb0e39bf 100644 --- a/packages/commons/src/constants.ts +++ b/packages/commons/src/constants.ts @@ -162,6 +162,7 @@ export const STORAGE = { DEFAULT_REVISION: '0-0000000000000000' }; -export const LOG_STATUS_MESSAGE = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'"; +export const LOG_STATUS_MESSAGE = + "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'"; export const LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`; export const LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`; diff --git a/packages/commons/src/helpers/pkg.ts b/packages/commons/src/helpers/pkg.ts index 2c58d1e75..6d7e47653 100644 --- a/packages/commons/src/helpers/pkg.ts +++ b/packages/commons/src/helpers/pkg.ts @@ -4,7 +4,11 @@ export interface DistTags { [key: string]: string; } -export function generatePackageMetadata(pkgName: string, version = '1.0.0', distTags: DistTags = { ['latest']: version }): Package { +export function generatePackageMetadata( + pkgName: string, + version = '1.0.0', + distTags: DistTags = { ['latest']: version } +): Package { // @ts-ignore return { _id: pkgName, @@ -38,7 +42,8 @@ export function generatePackageMetadata(pkgName: string, version = '1.0.0', dist name: 'foo', }, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, }, diff --git a/packages/config/package.json b/packages/config/package.json index 205044cfe..e97be693f 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -22,9 +22,6 @@ "build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps", "build": "pnpm run build:js && pnpm run build:types" }, - "devDependencies": { - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0" - }, "dependencies": { "@verdaccio/dev-commons": "workspace:5.0.0-alpha.0", "@verdaccio/logger": "workspace:5.0.0-alpha.0", diff --git a/packages/config/src/config-path.ts b/packages/config/src/config-path.ts index f5166be0f..e90db2a8d 100644 --- a/packages/config/src/config-path.ts +++ b/packages/config/src/config-path.ts @@ -37,7 +37,9 @@ function findConfigFile(configPath: string): string { throw new Error('no configuration files can be processed'); } - const primaryConf: any = _.find(configPaths, (configLocation: any) => fileExists(configLocation.path)); + const primaryConf: any = _.find(configPaths, (configLocation: any) => + fileExists(configLocation.path) + ); if (_.isNil(primaryConf) === false) { return primaryConf.path; } @@ -75,7 +77,8 @@ function updateStorageLinks(configLocation, defaultConfig): string { // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored, // If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used. // $FlowFixMe - let dataDir = process.env.XDG_DATA_HOME || Path.join(process.env.HOME as string, '.local', 'share'); + let dataDir = + process.env.XDG_DATA_HOME || Path.join(process.env.HOME as string, '.local', 'share'); if (folderExists(dataDir)) { dataDir = Path.resolve(Path.join(dataDir, pkgJSON.name, 'storage')); return defaultConfig.replace(/^storage: .\/storage$/m, `storage: ${dataDir}`); @@ -84,16 +87,17 @@ function updateStorageLinks(configLocation, defaultConfig): string { } function getConfigPaths(): SetupDirectory[] { - const listPaths: SetupDirectory[] = [getXDGDirectory(), getWindowsDirectory(), getRelativeDefaultDirectory(), getOldDirectory()].reduce(function ( - acc, - currentValue: any - ): SetupDirectory[] { + const listPaths: SetupDirectory[] = [ + getXDGDirectory(), + getWindowsDirectory(), + getRelativeDefaultDirectory(), + getOldDirectory(), + ].reduce(function (acc, currentValue: any): SetupDirectory[] { if (_.isUndefined(currentValue) === false) { acc.push(currentValue); } return acc; - }, - [] as SetupDirectory[]); + }, [] as SetupDirectory[]); return listPaths; } diff --git a/packages/config/src/config.ts b/packages/config/src/config.ts index f89abb08d..56e90b8a6 100644 --- a/packages/config/src/config.ts +++ b/packages/config/src/config.ts @@ -12,15 +12,27 @@ import { } from '@verdaccio/utils'; import { APP_ERROR } from '@verdaccio/dev-commons'; -import { PackageList, Config as AppConfig, Security, Logger } from '@verdaccio/types'; - -import { MatchedPackage, StartUpConfig } from '@verdaccio/dev-types'; +import { + PackageList, + Config as AppConfig, + Security, + Logger, + PackageAccess, +} from '@verdaccio/types'; const LoggerApi = require('@verdaccio/logger'); const strategicConfigProps = ['uplinks', 'packages']; const allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy']; +export type MatchedPackage = PackageAccess | void; + +export interface StartUpConfig { + storage: string; + plugins?: string; + self_path: string; +} + /** * Coordinates the application configuration */ diff --git a/packages/core/commons-api/src/index.ts b/packages/core/commons-api/src/index.ts index b57ded8da..8b9ee3abb 100644 --- a/packages/core/commons-api/src/index.ts +++ b/packages/core/commons-api/src/index.ts @@ -113,7 +113,9 @@ export function getBadRequest(customMessage: string): VerdaccioError { } export function getInternalError(customMessage?: string): VerdaccioError { - return customMessage ? getError(HTTP_STATUS.INTERNAL_ERROR, customMessage) : getError(HTTP_STATUS.INTERNAL_ERROR, API_ERROR.UNKNOWN_ERROR); + return customMessage + ? getError(HTTP_STATUS.INTERNAL_ERROR, customMessage) + : getError(HTTP_STATUS.INTERNAL_ERROR, API_ERROR.UNKNOWN_ERROR); } export function getUnauthorized(message = 'no credentials provided'): VerdaccioError { @@ -124,7 +126,9 @@ export function getForbidden(message = "can't use this filename"): VerdaccioErro return getError(HTTP_STATUS.FORBIDDEN, message); } -export function getServiceUnavailable(message: string = API_ERROR.RESOURCE_UNAVAILABLE): VerdaccioError { +export function getServiceUnavailable( + message: string = API_ERROR.RESOURCE_UNAVAILABLE +): VerdaccioError { return getError(HTTP_STATUS.SERVICE_UNAVAILABLE, message); } diff --git a/packages/core/file-locking/src/readFile.ts b/packages/core/file-locking/src/readFile.ts index a2ec68163..b9d217694 100644 --- a/packages/core/file-locking/src/readFile.ts +++ b/packages/core/file-locking/src/readFile.ts @@ -19,7 +19,11 @@ export type ReadFileOptions = { * @param {*} callback */ // eslint-disable-next-line @typescript-eslint/no-empty-function -function readFile(name: string, options: ReadFileOptions = {}, callback: Callback = (): void => {}): void { +function readFile( + name: string, + options: ReadFileOptions = {}, + callback: Callback = (): void => {} +): void { if (typeof options === 'function') { callback = options; options = {}; diff --git a/packages/core/file-locking/tests/lock.spec.ts b/packages/core/file-locking/tests/lock.spec.ts index e851b0018..ae875d6be 100644 --- a/packages/core/file-locking/tests/lock.spec.ts +++ b/packages/core/file-locking/tests/lock.spec.ts @@ -32,7 +32,9 @@ describe('testing locking', () => { test('file should fail to be found to be locked', (done) => { lockFile(getFilePath('package.fail.json'), (error: Error) => { - expect(error.message).toMatch(/ENOENT: no such file or directory, stat '(.*)package.fail.json'/); + expect(error.message).toMatch( + /ENOENT: no such file or directory, stat '(.*)package.fail.json'/ + ); done(); }); }); @@ -83,7 +85,9 @@ describe('testing locking', () => { parse: true, }; readFile(getFilePath('package.fail.json'), options, (error: Error) => { - expect(error.message).toMatch(/ENOENT: no such file or directory, open '(.*)package.fail.json'/); + expect(error.message).toMatch( + /ENOENT: no such file or directory, open '(.*)package.fail.json'/ + ); done(); }); }); diff --git a/packages/core/htpasswd/src/htpasswd.ts b/packages/core/htpasswd/src/htpasswd.ts index fb508365b..5e90409a0 100644 --- a/packages/core/htpasswd/src/htpasswd.ts +++ b/packages/core/htpasswd/src/htpasswd.ts @@ -4,7 +4,14 @@ import Path from 'path'; import { Callback, AuthConf, Config, IPluginAuth } from '@verdaccio/types'; import { unlockFile } from '@verdaccio/file-locking'; -import { verifyPassword, lockAndRead, parseHTPasswd, addUserToHTPasswd, changePasswordToHTPasswd, sanityCheck } from './utils'; +import { + verifyPassword, + lockAndRead, + parseHTPasswd, + addUserToHTPasswd, + changePasswordToHTPasswd, + sanityCheck, +} from './utils'; export interface VerdaccioConfigApp extends Config { file: string; @@ -197,7 +204,12 @@ export default class HTPasswd implements IPluginAuth { * @param {function} cd * @returns {function} */ - public changePassword(user: string, password: string, newPassword: string, realCb: Callback): void { + public changePassword( + user: string, + password: string, + newPassword: string, + realCb: Callback + ): void { lockAndRead(this.path, (err, res) => { let locked = false; const pathPassFile = this.path; diff --git a/packages/core/htpasswd/src/utils.ts b/packages/core/htpasswd/src/utils.ts index f27a1024a..c84d01dd7 100644 --- a/packages/core/htpasswd/src/utils.ts +++ b/packages/core/htpasswd/src/utils.ts @@ -95,7 +95,13 @@ export function addUserToHTPasswd(body: string, user: string, passwd: string): s * @param {number} maxUsers * @returns {object} */ -export function sanityCheck(user: string, password: string, verifyFn: Callback, users: {}, maxUsers: number): HttpError | null { +export function sanityCheck( + user: string, + password: string, + verifyFn: Callback, + users: {}, + maxUsers: number +): HttpError | null { let err; // check for user or password @@ -144,7 +150,12 @@ export function getCryptoPassword(password: string): string { * @param {string} newPasswd * @returns {string} */ -export function changePasswordToHTPasswd(body: string, user: string, passwd: string, newPasswd: string): string { +export function changePasswordToHTPasswd( + body: string, + user: string, + passwd: string, + newPasswd: string +): string { let lines = body.split('\n'); lines = lines.map((line) => { const [username, password] = line.split(':', 3); diff --git a/packages/core/htpasswd/tests/utils.test.ts b/packages/core/htpasswd/tests/utils.test.ts index 40624ff11..6d13d3874 100644 --- a/packages/core/htpasswd/tests/utils.test.ts +++ b/packages/core/htpasswd/tests/utils.test.ts @@ -1,6 +1,14 @@ import crypto from 'crypto'; -import { verifyPassword, lockAndRead, parseHTPasswd, addUserToHTPasswd, sanityCheck, changePasswordToHTPasswd, getCryptoPassword } from '../src/utils'; +import { + verifyPassword, + lockAndRead, + parseHTPasswd, + addUserToHTPasswd, + sanityCheck, + changePasswordToHTPasswd, + getCryptoPassword, +} from '../src/utils'; const mockReadFile = jest.fn(); const mockUnlockFile = jest.fn(); @@ -69,7 +77,10 @@ describe('verifyPassword', () => { expect(verifyPassword(input[0], input[1])).toBeTruthy(); }); it('should verify the bcrypt password with false', () => { - const input = ['testpasswordchanged', '$2y$04$Wqed4yN0OktGbiUdxSTwtOva1xfESfkNIZfcS9/vmHLsn3.lkFxJO']; + const input = [ + 'testpasswordchanged', + '$2y$04$Wqed4yN0OktGbiUdxSTwtOva1xfESfkNIZfcS9/vmHLsn3.lkFxJO', + ]; expect(verifyPassword(input[0], input[1])).toBeFalsy(); }); }); @@ -116,7 +127,9 @@ describe('addUserToHTPasswd - crypto', () => { jest.doMock('../src/crypt3.ts', () => false); const input = ['', 'username', 'password']; const utils = require('../src/utils.ts'); - expect(utils.addUserToHTPasswd(input[0], input[1], input[2])).toEqual('username:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=:autocreated 2018-01-14T11:17:40.712Z\n'); + expect(utils.addUserToHTPasswd(input[0], input[1], input[2])).toEqual( + 'username:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=:autocreated 2018-01-14T11:17:40.712Z\n' + ); }); }); @@ -229,7 +242,9 @@ describe('changePasswordToHTPasswd', () => { const body = 'root:$6qLTHoPfGLy2:autocreated 2018-08-20T13:38:12.164Z'; - expect(changePasswordToHTPasswd(body, 'root', 'demo123', 'demo123')).toEqual('root:ABfaAAjDKIgfw:autocreated 2018-08-20T13:38:12.164Z'); + expect(changePasswordToHTPasswd(body, 'root', 'demo123', 'demo123')).toEqual( + 'root:ABfaAAjDKIgfw:autocreated 2018-08-20T13:38:12.164Z' + ); }); test('should change the password when crypt3 is not available', () => { diff --git a/packages/core/local-storage/src/local-database.ts b/packages/core/local-storage/src/local-database.ts index 0374816ce..b1859cf2b 100644 --- a/packages/core/local-storage/src/local-database.ts +++ b/packages/core/local-storage/src/local-database.ts @@ -6,7 +6,17 @@ import buildDebug from 'debug'; import _ from 'lodash'; import async from 'async'; import mkdirp from 'mkdirp'; -import { Callback, Config, IPackageStorage, IPluginStorage, LocalStorage, Logger, StorageList, Token, TokenFilter } from '@verdaccio/types'; +import { + Callback, + Config, + IPackageStorage, + IPluginStorage, + LocalStorage, + Logger, + StorageList, + Token, + TokenFilter, +} from '@verdaccio/types'; import level from 'level'; import { getInternalError } from '@verdaccio/commons-api'; @@ -82,7 +92,11 @@ class LocalDatabase implements IPluginStorage<{}> { } } - public search(onPackage: Callback, onEnd: Callback, validateName: (name: string) => boolean): void { + public search( + onPackage: Callback, + onEnd: Callback, + validateName: (name: string) => boolean + ): void { const storages = this._getCustomPackageLocalStorages(); debug(`search custom local packages: %o`, JSON.stringify(storages)); const base = Path.dirname(this.config.self_path); @@ -182,7 +196,10 @@ class LocalDatabase implements IPluginStorage<{}> { this.get((err, data) => { if (err) { cb(getInternalError('error remove private package')); - this.logger.error({ err }, '[local-storage/remove]: remove the private package has failed @{err}'); + this.logger.error( + { err }, + '[local-storage/remove]: remove the private package has failed @{err}' + ); debug('error on remove package %o', name); } @@ -213,7 +230,9 @@ class LocalDatabase implements IPluginStorage<{}> { public getPackageStorage(packageName: string): IPackageStorage { const packageAccess = this.config.getMatchedPackagesSpec(packageName); - const packagePath: string = this._getLocalStoragePath(packageAccess ? packageAccess.storage : undefined); + const packagePath: string = this._getLocalStoragePath( + packageAccess ? packageAccess.storage : undefined + ); debug('storage path selected: ', packagePath); if (_.isString(packagePath) === false) { @@ -221,7 +240,10 @@ class LocalDatabase implements IPluginStorage<{}> { return; } - const packageStoragePath: string = Path.join(Path.resolve(Path.dirname(this.config.self_path || ''), packagePath), packageName); + const packageStoragePath: string = Path.join( + Path.resolve(Path.dirname(this.config.self_path || ''), packagePath), + packageName + ); debug('storage absolute path: ', packageStoragePath); @@ -317,8 +339,12 @@ class LocalDatabase implements IPluginStorage<{}> { debug('sync database started'); if (this.locked) { - this.logger.error('Database is locked, please check error message printed during startup to prevent data loss.'); - return new Error('Verdaccio database is locked, please contact your administrator to checkout logs during verdaccio startup.'); + this.logger.error( + 'Database is locked, please check error message printed during startup to prevent data loss.' + ); + return new Error( + 'Verdaccio database is locked, please contact your administrator to checkout logs during verdaccio startup.' + ); } // Uses sync to prevent ugly race condition try { @@ -383,7 +409,9 @@ class LocalDatabase implements IPluginStorage<{}> { } private _dbGenPath(dbName: string, config: Config): string { - return Path.join(Path.resolve(Path.dirname(config.self_path || ''), config.storage as string, dbName)); + return Path.join( + Path.resolve(Path.dirname(config.self_path || ''), config.storage as string, dbName) + ); } /** @@ -404,7 +432,10 @@ class LocalDatabase implements IPluginStorage<{}> { // Only recreate if file not found to prevent data loss if (err.code !== noSuchFile) { this.locked = true; - this.logger.error('Failed to read package database file, please check the error printed below:\n', `File Path: ${this.path}\n\n ${err.message}`); + this.logger.error( + 'Failed to read package database file, please check the error printed below:\n', + `File Path: ${this.path}\n\n ${err.message}` + ); } return emptyDatabase; diff --git a/packages/core/local-storage/src/local-fs.ts b/packages/core/local-storage/src/local-fs.ts index f743e7d54..4abdde057 100644 --- a/packages/core/local-storage/src/local-fs.ts +++ b/packages/core/local-storage/src/local-fs.ts @@ -78,7 +78,13 @@ export default class LocalFS implements ILocalFSPackageManager { * @param {*} transformPackage * @param {*} onEnd */ - public updatePackage(name: string, updateHandler: Callback, onWrite: Callback, transformPackage: Function, onEnd: Callback): void { + public updatePackage( + name: string, + updateHandler: Callback, + onWrite: Callback, + transformPackage: Function, + onEnd: Callback + ): void { this._lockAndReadJSON(pkgFileName, (err, json) => { let locked = false; const self = this; @@ -127,7 +133,10 @@ export default class LocalFS implements ILocalFSPackageManager { }); } - public deletePackage(packageName: string, callback: (err: NodeJS.ErrnoException | null) => void): void { + public deletePackage( + packageName: string, + callback: (err: NodeJS.ErrnoException | null) => void + ): void { debug('delete a package %o', packageName); return fs.unlink(this._getStorage(packageName), callback); @@ -190,7 +199,10 @@ export default class LocalFS implements ILocalFSPackageManager { if (exists) { uploadStream.emit('error', fSError(fileExist)); } else { - const temporalName = path.join(this.path, `${name}.tmp-${String(Math.random()).replace(/^0\./, '')}`); + const temporalName = path.join( + this.path, + `${name}.tmp-${String(Math.random()).replace(/^0\./, '')}` + ); debug('write a temporal name %o', temporalName); const file = fs.createWriteStream(temporalName); const removeTempFile = (): void => fs.unlink(temporalName, () => {}); diff --git a/packages/core/local-storage/src/pkg-utils.ts b/packages/core/local-storage/src/pkg-utils.ts index 8198f63c5..16052f14c 100644 --- a/packages/core/local-storage/src/pkg-utils.ts +++ b/packages/core/local-storage/src/pkg-utils.ts @@ -17,7 +17,10 @@ export function loadPrivatePackages(path: string, logger: Logger): LocalStorage try { db = JSON.parse(data); } catch (err) { - logger.error(`Package database file corrupted (invalid JSON), please check the error printed below.\nFile Path: ${path}`, err); + logger.error( + `Package database file corrupted (invalid JSON), please check the error printed below.\nFile Path: ${path}`, + err + ); throw Error('Package database file corrupted (invalid JSON)'); } diff --git a/packages/core/local-storage/src/utils.ts b/packages/core/local-storage/src/utils.ts index 7a24f0e82..bb9c638c4 100644 --- a/packages/core/local-storage/src/utils.ts +++ b/packages/core/local-storage/src/utils.ts @@ -31,7 +31,10 @@ function hasScope(file: string): boolean { } /* eslint-disable no-async-promise-executor */ -export async function findPackages(storagePath: string, validationHandler: Function): Promise<{ name: string; path: string }[]> { +export async function findPackages( + storagePath: string, + validationHandler: Function +): Promise<{ name: string; path: string }[]> { const listPackages: { name: string; path: string }[] = []; return new Promise(async (resolve, reject) => { try { diff --git a/packages/core/local-storage/tests/__fixtures__/pkg.js b/packages/core/local-storage/tests/__fixtures__/pkg.js index 044a38cc2..c5f6f2b2d 100644 --- a/packages/core/local-storage/tests/__fixtures__/pkg.js +++ b/packages/core/local-storage/tests/__fixtures__/pkg.js @@ -30,7 +30,8 @@ const json = { _nodeVersion: '8.7.0', _npmUser: {}, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', tarball: 'http://localhost:5555/@scope/pk1-test/-/@scope/pk1-test-1.0.6.tgz', }, diff --git a/packages/core/local-storage/tests/local-database.test.ts b/packages/core/local-storage/tests/local-database.test.ts index f78bbe236..08d745b42 100644 --- a/packages/core/local-storage/tests/local-database.test.ts +++ b/packages/core/local-storage/tests/local-database.test.ts @@ -24,7 +24,9 @@ let loadPrivatePackages; describe('Local Database', () => { beforeEach(() => { const writeMock = jest.spyOn(fs, 'writeFileSync').mockImplementation(); - loadPrivatePackages = jest.spyOn(pkgUtils, 'loadPrivatePackages').mockReturnValue({ list: [], secret: '' }); + loadPrivatePackages = jest + .spyOn(pkgUtils, 'loadPrivatePackages') + .mockReturnValue({ list: [], secret: '' }); locaDatabase = new LocalDatabase(optionsPlugin.config, optionsPlugin.logger); (locaDatabase as LocalDatabase).clean(); writeMock.mockClear(); @@ -77,7 +79,13 @@ describe('Local Database', () => { if (storage) { const storagePath = path.normalize((storage as ILocalFSPackageManager).path).toLowerCase(); - expect(storagePath).toBe(path.normalize(path.join(__dirname, '__fixtures__', optionsPlugin.config.storage || '', pkgName)).toLowerCase()); + expect(storagePath).toBe( + path + .normalize( + path.join(__dirname, '__fixtures__', optionsPlugin.config.storage || '', pkgName) + ) + .toLowerCase() + ); } }); @@ -90,7 +98,17 @@ describe('Local Database', () => { if (storage) { const storagePath = path.normalize((storage as ILocalFSPackageManager).path).toLowerCase(); expect(storagePath).toBe( - path.normalize(path.join(__dirname, '__fixtures__', optionsPlugin.config.storage || '', 'private_folder', pkgName)).toLowerCase() + path + .normalize( + path.join( + __dirname, + '__fixtures__', + optionsPlugin.config.storage || '', + 'private_folder', + pkgName + ) + ) + .toLowerCase() ); } }); @@ -153,7 +171,11 @@ describe('Local Database', () => { const scopedPackages = ['@pkg1/test']; const stats = { mtime: new Date() }; jest.spyOn(fs, 'stat').mockImplementation((_, cb) => cb(null, stats as fs.Stats)); - jest.spyOn(fs, 'readdir').mockImplementation((storePath, cb) => cb(null, storePath.match('test-storage') ? scopedPackages : [])); + jest + .spyOn(fs, 'readdir') + .mockImplementation((storePath, cb) => + cb(null, storePath.match('test-storage') ? scopedPackages : []) + ); callSearch(locaDatabase, 1, done); }); @@ -162,7 +184,11 @@ describe('Local Database', () => { const nonScopedPackages = ['pkg1', 'pkg2']; const stats = { mtime: new Date() }; jest.spyOn(fs, 'stat').mockImplementation((_, cb) => cb(null, stats as fs.Stats)); - jest.spyOn(fs, 'readdir').mockImplementation((storePath, cb) => cb(null, storePath.match('test-storage') ? nonScopedPackages : [])); + jest + .spyOn(fs, 'readdir') + .mockImplementation((storePath, cb) => + cb(null, storePath.match('test-storage') ? nonScopedPackages : []) + ); const db = new LocalDatabase( assign({}, optionsPlugin.config, { @@ -176,7 +202,9 @@ describe('Local Database', () => { }); test('should fails on read the storage', (done) => { - const spyInstance = jest.spyOn(fs, 'readdir').mockImplementation((_, cb) => cb(Error('fails'), null)); + const spyInstance = jest + .spyOn(fs, 'readdir') + .mockImplementation((_, cb) => cb(Error('fails'), null)); const db = new LocalDatabase( assign({}, optionsPlugin.config, { @@ -267,7 +295,9 @@ describe('Local Database', () => { db.createReadStream.mockImplementation(() => stream); setTimeout(() => events.once['error'](new Error('Unexpected error!'))); - await expect(locaDatabase.readTokens({ user: 'someUser' })).rejects.toThrow('Unexpected error!'); + await expect(locaDatabase.readTokens({ user: 'someUser' })).rejects.toThrow( + 'Unexpected error!' + ); }); }); }); diff --git a/packages/core/local-storage/tests/local-fs.test.ts b/packages/core/local-storage/tests/local-fs.test.ts index 2d1b848d1..5d6ea58dc 100644 --- a/packages/core/local-storage/tests/local-fs.test.ts +++ b/packages/core/local-storage/tests/local-fs.test.ts @@ -42,7 +42,10 @@ describe('Local FS test', () => { describe('readPackage() group', () => { test('readPackage() success', (done) => { - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/readme-test'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/readme-test'), + logger + ); localFs.readPackage(pkgFileName, (err) => { expect(err).toBeNull(); @@ -51,7 +54,10 @@ describe('Local FS test', () => { }); test('readPackage() fails', (done) => { - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/readme-testt'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/readme-testt'), + logger + ); localFs.readPackage(pkgFileName, (err) => { expect(err).toBeTruthy(); @@ -60,7 +66,10 @@ describe('Local FS test', () => { }); test('readPackage() fails corrupt', (done) => { - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/readme-test-corrupt'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/readme-test-corrupt'), + logger + ); localFs.readPackage('corrupt.js', (err) => { expect(err).toBeTruthy(); @@ -108,7 +117,10 @@ describe('Local FS test', () => { }); test('removePackage() success', (done) => { - const localFs: ILocalPackageManager = new LocalDriver(path.join(localTempStorage, '_toDelete'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(localTempStorage, '_toDelete'), + logger + ); localFs.removePackage((error) => { expect(error).toBeNull(); done(); @@ -116,7 +128,10 @@ describe('Local FS test', () => { }); test('removePackage() fails', (done) => { - const localFs: ILocalPackageManager = new LocalDriver(path.join(localTempStorage, '_toDelete_fake'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(localTempStorage, '_toDelete_fake'), + logger + ); localFs.removePackage((error) => { expect(error).toBeTruthy(); expect(error.code).toBe('ENOENT'); @@ -127,7 +142,10 @@ describe('Local FS test', () => { describe('readTarball() group', () => { test('readTarball() success', (done) => { - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/readme-test'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/readme-test'), + logger + ); const readTarballStream = localFs.readTarball('test-readme-0.0.0.tgz'); readTarballStream.on('error', function (err) { @@ -148,7 +166,10 @@ describe('Local FS test', () => { }); test('readTarball() fails', (done) => { - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/readme-test'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/readme-test'), + logger + ); const readTarballStream = localFs.readTarball('file-does-not-exist-0.0.0.tgz'); readTarballStream.on('error', function (err) { @@ -167,8 +188,14 @@ describe('Local FS test', () => { test('writeTarball() success', (done) => { const newFileName = 'new-readme-0.0.0.tgz'; - const readmeStorage: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/readme-test'), logger); - const writeStorage: ILocalPackageManager = new LocalDriver(path.join(__dirname, '../_storage'), logger); + const readmeStorage: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/readme-test'), + logger + ); + const writeStorage: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '../_storage'), + logger + ); const readTarballStream = readmeStorage.readTarball('test-readme-0.0.0.tgz'); const writeTarballStream = writeStorage.writeTarball(newFileName); @@ -207,7 +234,10 @@ describe('Local FS test', () => { test('writeTarball() abort', (done) => { const newFileLocationFolder: string = path.join(localTempStorage, '_writeTarball'); const newFileName = 'new-readme-abort-0.0.0.tgz'; - const readmeStorage: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/readme-test'), logger); + const readmeStorage: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/readme-test'), + logger + ); const writeStorage: ILocalPackageManager = new LocalDriver(newFileLocationFolder, logger); const readTarballStream = readmeStorage.readTarball('test-readme-0.0.0.tgz'); const writeTarballStream = writeStorage.writeTarball(newFileName); @@ -249,7 +279,10 @@ describe('Local FS test', () => { }); const LocalDriver = require('../src/local-fs').default; - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/update-package'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/update-package'), + logger + ); localFs.updatePackage('updatePackage', updateHandler, onWrite, transform, () => { expect(transform).toHaveBeenCalledTimes(1); @@ -268,7 +301,10 @@ describe('Local FS test', () => { }; }); require('../src/local-fs').default; - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/update-package'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/update-package'), + logger + ); localFs.updatePackage('updatePackage', updateHandler, onWrite, transform, (err) => { expect(err).not.toBeNull(); @@ -287,7 +323,10 @@ describe('Local FS test', () => { }; }); const LocalDriver = require('../src/local-fs').default; - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/update-package'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/update-package'), + logger + ); localFs.updatePackage('updatePackage', updateHandler, onWrite, transform, (err) => { expect(err).not.toBeNull(); @@ -306,7 +345,10 @@ describe('Local FS test', () => { }; }); const LocalDriver = require('../src/local-fs').default; - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/update-package'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/update-package'), + logger + ); localFs.updatePackage('updatePackage', updateHandler, onWrite, transform, (err) => { expect(err).not.toBeNull(); @@ -326,7 +368,10 @@ describe('Local FS test', () => { }); const LocalDriver = require('../src/local-fs').default; - const localFs: ILocalPackageManager = new LocalDriver(path.join(__dirname, '__fixtures__/update-package'), logger); + const localFs: ILocalPackageManager = new LocalDriver( + path.join(__dirname, '__fixtures__/update-package'), + logger + ); const updateHandler = jest.fn((_name, cb) => { cb(fSError('something wrong', 500)); }); diff --git a/packages/core/readme/tests/readme.spec.ts b/packages/core/readme/tests/readme.spec.ts index 3d155bfe5..6bcf44021 100644 --- a/packages/core/readme/tests/readme.spec.ts +++ b/packages/core/readme/tests/readme.spec.ts @@ -42,25 +42,37 @@ describe('readme', () => { }); test('should parse basic / local storage', () => { - expect(parseReadme('[Local Storage](javascript:alert(JSON.stringify(localStorage)))')).toEqual('

Local Storage

'); + expect( + parseReadme('[Local Storage](javascript:alert(JSON.stringify(localStorage)))') + ).toEqual('

Local Storage

'); }); test('should parse basic / case insensitive', () => { - expect(parseReadme("[CaseInsensitive](JaVaScRiPt:alert('CaseInsensitive'))")).toEqual('

CaseInsensitive

'); + expect(parseReadme("[CaseInsensitive](JaVaScRiPt:alert('CaseInsensitive'))")).toEqual( + '

CaseInsensitive

' + ); }); test('should parse basic / url', () => { - expect(parseReadme("[URL](javascript://www.google.com%0Aalert('URL'))")).toEqual('

URL

'); + expect(parseReadme("[URL](javascript://www.google.com%0Aalert('URL'))")).toEqual( + '

URL

' + ); }); test('should parse basic / in quotes', () => { - expect(parseReadme('[In Quotes](\'javascript:alert("InQuotes")\')')).toEqual('

In Quotes

'); + expect(parseReadme('[In Quotes](\'javascript:alert("InQuotes")\')')).toEqual( + '

In Quotes

' + ); }); }); describe('should parse images', () => { test('in quotes', () => { - expect(parseReadme('![Escape SRC - onload](https://www.example.com/image.png"onload="alert(\'ImageOnLoad\'))')).toEqual( + expect( + parseReadme( + '![Escape SRC - onload](https://www.example.com/image.png"onload="alert(\'ImageOnLoad\'))' + ) + ).toEqual( '

Escape SRC - onload

' ); }); @@ -78,17 +90,23 @@ describe('readme', () => { }); test('xss / white space cookie', () => { - expect(parseReadme('[XSS](j a v a s c r i p t:prompt(document.cookie))')).toEqual( - '

[XSS](j a v a s c r i p t:prompt(document.cookie))

' - ); + expect( + parseReadme('[XSS](j a v a s c r i p t:prompt(document.cookie))') + ).toEqual('

[XSS](j a v a s c r i p t:prompt(document.cookie))

'); }); test('xss / data test/html', () => { - expect(parseReadme('[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)')).toEqual('

XSS

'); + expect( + parseReadme('[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)') + ).toEqual('

XSS

'); }); test('xss / data test/html encoded', () => { - expect(parseReadme('[XSS](javascript:alert('XSS'))')).toEqual( + expect( + parseReadme( + '[XSS](javascript:alert('XSS'))' + ) + ).toEqual( '

XSS

' ); }); @@ -98,7 +116,9 @@ describe('readme', () => { }); test('xss / js window error alert', () => { - expect(parseReadme('[XSS](javascript:window.onerror=alert;throw%20document.cookie)')).toEqual('

XSS

'); + expect(parseReadme('[XSS](javascript:window.onerror=alert;throw%20document.cookie)')).toEqual( + '

XSS

' + ); }); test('xss / js window encoded prompt', () => { @@ -110,15 +130,21 @@ describe('readme', () => { }); test('xss / js window encoded window error alert multiple statement', () => { - expect(parseReadme('[XSS](javascript:window.onerror=alert;throw%20document.cookie)')).toEqual('

XSS

'); + expect(parseReadme('[XSS](javascript:window.onerror=alert;throw%20document.cookie)')).toEqual( + '

XSS

' + ); }); test('xss / js window encoded window error alert throw error', () => { - expect(parseReadme('[XSS](javascript://%0d%0awindow.onerror=alert;throw%20document.cookie)')).toEqual('

XSS

'); + expect( + parseReadme('[XSS](javascript://%0d%0awindow.onerror=alert;throw%20document.cookie)') + ).toEqual('

XSS

'); }); test('xss / js window encoded data text/html base 64', () => { - expect(parseReadme('[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)')).toEqual('

XSS

'); + expect( + parseReadme('[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)') + ).toEqual('

XSS

'); }); test('xss / js vbscript alert', () => { @@ -143,7 +169,9 @@ describe('readme', () => { }); test('xss / js case #5', () => { - expect(parseReadme('[XSS](Javas%26%2399;ript:alert(1))')).toEqual('

XSS

'); + expect(parseReadme('[XSS](Javas%26%2399;ript:alert(1))')).toEqual( + '

XSS

' + ); }); test('xss / js case #6', () => { @@ -157,34 +185,48 @@ describe('readme', () => { describe('xss / js url', () => { test('xss / case #1', () => { - expect(parseReadme('[XSS](javascript://www.google.com%0Aprompt(1))')).toEqual('

XSS

'); + expect(parseReadme('[XSS](javascript://www.google.com%0Aprompt(1))')).toEqual( + '

XSS

' + ); }); test('xss / case #2', () => { - expect(parseReadme('[XSS](javascript://%0d%0aconfirm(1);com)')).toEqual('

XSS

'); + expect(parseReadme('[XSS](javascript://%0d%0aconfirm(1);com)')).toEqual( + '

XSS

' + ); }); test('xss / case #3', () => { - expect(parseReadme('[XSS](javascript:window.onerror=confirm;throw%201)')).toEqual('

XSS

'); + expect(parseReadme('[XSS](javascript:window.onerror=confirm;throw%201)')).toEqual( + '

XSS

' + ); }); test('xss / case #4', () => { - expect(parseReadme('[XSS](�javascript:alert(document.domain))')).toEqual('

XSS

'); + expect(parseReadme('[XSS](�javascript:alert(document.domain))')).toEqual( + '

XSS

' + ); }); test('xss / case #5', () => { - expect(parseReadme('![XSS](javascript:prompt(document.cookie))\\')).toEqual('

XSS\\

'); + expect(parseReadme('![XSS](javascript:prompt(document.cookie))\\')).toEqual( + '

XSS\\

' + ); }); test('xss / case #6', () => { - expect(parseReadme('![XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)\\')).toEqual( + expect( + parseReadme('![XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)\\') + ).toEqual( '

XSS\\

' ); }); // FIXME: requires proper parsing test.skip('xss / case #7', () => { - expect(parseReadme(`![XSS'"\`onerror=prompt(document.cookie)](x)\\`)).toEqual('

![XSS\'\\"`onerror=prompt(document.cookie)](x)\\\\

'); + expect(parseReadme(`![XSS'"\`onerror=prompt(document.cookie)](x)\\`)).toEqual( + '

![XSS\'\\"`onerror=prompt(document.cookie)](x)\\\\

' + ); }); }); }); diff --git a/packages/core/types/index.d.ts b/packages/core/types/index.d.ts index 07a97a6a9..81f234f7d 100644 --- a/packages/core/types/index.d.ts +++ b/packages/core/types/index.d.ts @@ -410,7 +410,11 @@ declare module '@verdaccio/types' { getSecret(): Promise; setSecret(secret: string): Promise; getPackageStorage(packageInfo: string): IPackageStorage; - search(onPackage: onSearchPackage, onEnd: onEndSearchPackage, validateName: onValidatePackage): void; + search( + onPackage: onSearchPackage, + onEnd: onEndSearchPackage, + validateName: onValidatePackage + ): void; } type StorageUpdateCallback = (data: Package, cb: CallbackAction) => void; @@ -444,7 +448,13 @@ declare module '@verdaccio/types' { } interface StoragePackageActions extends TarballActions { - addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void; + addVersion( + name: string, + version: string, + metadata: Version, + tag: StringValue, + callback: Callback + ): void; mergeTags(name: string, tags: MergeTags, callback: Callback): void; removePackage(name: string, callback: Callback): void; changePackage(name: string, metadata: Package, revision: string, callback: Callback): void; @@ -521,9 +531,17 @@ declare module '@verdaccio/types' { allow_publish?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): void; allow_access?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): void; allow_unpublish?(user: RemoteUser, pkg: T & PackageAccess, cb: AuthAccessCallback): void; - allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void; + allow_publish?( + user: RemoteUser, + pkg: AllowAccess & PackageAccess, + cb: AuthAccessCallback + ): void; allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void; - allow_unpublish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void; + allow_unpublish?( + user: RemoteUser, + pkg: AllowAccess & PackageAccess, + cb: AuthAccessCallback + ): void; apiJWTmiddleware?(helpers: any): Function; } diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 2c17bcfa2..3212bbb5b 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -25,7 +25,6 @@ "@verdaccio/auth": "workspace:5.0.0-alpha.0", "@verdaccio/config": "workspace:5.0.0-alpha.0", "@verdaccio/dev-commons": "workspace:5.0.0-alpha.0", - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/types": "workspace:*", "@verdaccio/utils": "workspace:5.0.0-alpha.0" }, diff --git a/packages/hooks/src/notify.ts b/packages/hooks/src/notify.ts index 32383b86b..df8c7c955 100644 --- a/packages/hooks/src/notify.ts +++ b/packages/hooks/src/notify.ts @@ -7,7 +7,12 @@ import { notifyRequest } from './notify-request'; type TemplateMetadata = Package & { publishedPackage: string }; -export function handleNotify(metadata: Package, notifyEntry, remoteUser: RemoteUser, publishedPackage: string): Promise | void { +export function handleNotify( + metadata: Package, + notifyEntry, + remoteUser: RemoteUser, + publishedPackage: string +): Promise | void { let regex; if (metadata.name && notifyEntry.packagePattern) { regex = new RegExp(notifyEntry.packagePattern, notifyEntry.packagePatternFlags || ''); @@ -60,17 +65,34 @@ export function handleNotify(metadata: Package, notifyEntry, remoteUser: RemoteU return notifyRequest(options, content); } -export function sendNotification(metadata: Package, notify: Notification, remoteUser: RemoteUser, publishedPackage: string): Promise { +export function sendNotification( + metadata: Package, + notify: Notification, + remoteUser: RemoteUser, + publishedPackage: string +): Promise { return handleNotify(metadata, notify, remoteUser, publishedPackage) as Promise; } -export function notify(metadata: Package, config: Config, remoteUser: RemoteUser, publishedPackage: string): Promise | void { +export function notify( + metadata: Package, + config: Config, + remoteUser: RemoteUser, + publishedPackage: string +): Promise | void { if (config.notify) { if (config.notify.content) { - return sendNotification(metadata, (config.notify as unknown) as Notification, remoteUser, publishedPackage); + return sendNotification( + metadata, + (config.notify as unknown) as Notification, + remoteUser, + publishedPackage + ); } // multiple notifications endpoints PR #108 - return Promise.all(_.map(config.notify, (key) => sendNotification(metadata, key, remoteUser, publishedPackage))); + return Promise.all( + _.map(config.notify, (key) => sendNotification(metadata, key, remoteUser, publishedPackage)) + ); } return Promise.resolve(); diff --git a/packages/hooks/test/notify.spec.ts b/packages/hooks/test/notify.spec.ts index 5815f0c54..f0cbe8494 100644 --- a/packages/hooks/test/notify.spec.ts +++ b/packages/hooks/test/notify.spec.ts @@ -15,8 +15,12 @@ const parseConfigurationNotifyFile = (name) => { return parseConfigurationFile(`notify/${name}`); }; const singleNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('single.notify')); -const singleHeaderNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('single.header.notify')); -const packagePatternNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('single.packagePattern.notify')); +const singleHeaderNotificationConfig = parseConfigFile( + parseConfigurationNotifyFile('single.header.notify') +); +const packagePatternNotificationConfig = parseConfigFile( + parseConfigurationNotifyFile('single.packagePattern.notify') +); const multiNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('multiple.notify')); describe('Notifications:: Notify', () => { diff --git a/packages/hooks/test/request.spec.ts b/packages/hooks/test/request.spec.ts index 002af544f..54e3a9490 100644 --- a/packages/hooks/test/request.spec.ts +++ b/packages/hooks/test/request.spec.ts @@ -38,7 +38,10 @@ describe('Notifications:: notifyRequest', () => { }); const notification = require('../src/notify-request'); - const args = [{ errorMessage: 'bad data' }, 'notify service has thrown an error: @{errorMessage}']; + const args = [ + { errorMessage: 'bad data' }, + 'notify service has thrown an error: @{errorMessage}', + ]; await expect(notification.notifyRequest(options, content)).rejects.toEqual(API_ERROR.BAD_DATA); expect(logger.logger.error).toHaveBeenCalledWith(...args); @@ -55,7 +58,10 @@ describe('Notifications:: notifyRequest', () => { }); const notification = require('../src/notify-request'); - const args = [{ errorMessage: 'bad data' }, 'notify service has thrown an error: @{errorMessage}']; + const args = [ + { errorMessage: 'bad data' }, + 'notify service has thrown an error: @{errorMessage}', + ]; await expect(notification.notifyRequest(options, content)).rejects.toEqual(API_ERROR.BAD_DATA); expect(logger.logger.error).toHaveBeenCalledWith(...args); @@ -75,7 +81,9 @@ describe('Notifications:: notifyRequest', () => { const infoArgs = [{ content }, 'A notification has been shipped: @{content}']; const debugArgs = [{ body: 'Successfully delivered' }, ' body: @{body}']; - await expect(notification.notifyRequest(options, content)).resolves.toEqual('Successfully delivered'); + await expect(notification.notifyRequest(options, content)).resolves.toEqual( + 'Successfully delivered' + ); expect(logger.logger.info).toHaveBeenCalledWith(...infoArgs); expect(logger.logger.debug).toHaveBeenCalledWith(...debugArgs); }); diff --git a/packages/loaders/package.json b/packages/loaders/package.json index d79d23e41..62f9dcfcd 100644 --- a/packages/loaders/package.json +++ b/packages/loaders/package.json @@ -20,7 +20,6 @@ }, "devDependencies": { "@verdaccio/mock": "workspace:5.0.0-alpha.0", - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/config": "workspace:5.0.0-alpha.0", "@verdaccio/commons-api": "workspace:*", "@verdaccio/types": "workspace:*" diff --git a/packages/loaders/src/plugin-loader.ts b/packages/loaders/src/plugin-loader.ts index 23bc50f9c..7f0e21144 100644 --- a/packages/loaders/src/plugin-loader.ts +++ b/packages/loaders/src/plugin-loader.ts @@ -50,7 +50,13 @@ function isES6(plugin): boolean { * @param {*} sanityCheck callback that check the shape that should fulfill the plugin * @return {Array} list of plugins */ -export function loadPlugin>(config: Config, pluginConfigs: any = {}, params: any, sanityCheck: any, prefix: string = 'verdaccio'): any[] { +export function loadPlugin>( + config: Config, + pluginConfigs: any = {}, + params: any, + sanityCheck: any, + prefix: string = 'verdaccio' +): any[] { return Object.keys(pluginConfigs).map( (pluginId: string): IPlugin => { let plugin; @@ -94,19 +100,27 @@ export function loadPlugin>(config: Config, pluginConfigs: } if (plugin === null) { - logger.error({ content: pluginId, prefix }, 'plugin not found. try npm install @{prefix}-@{content}'); + logger.error( + { content: pluginId, prefix }, + 'plugin not found. try npm install @{prefix}-@{content}' + ); throw Error(` ${prefix}-${pluginId} plugin not found. try "npm install ${prefix}-${pluginId}"`); } if (!isValid(plugin)) { - logger.error({ content: pluginId }, '@{prefix}-@{content} plugin does not have the right code structure'); + logger.error( + { content: pluginId }, + '@{prefix}-@{content} plugin does not have the right code structure' + ); throw Error(`"${pluginId}" plugin does not have the right code structure`); } /* eslint new-cap:off */ try { - plugin = isES6(plugin) ? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params) : plugin(pluginConfigs[pluginId], params); + plugin = isES6(plugin) + ? new plugin.default(mergeConfig(config, pluginConfigs[pluginId]), params) + : plugin(pluginConfigs[pluginId], params); } catch (error) { plugin = null; logger.error({ error, pluginId }, 'error loading a plugin @{pluginId}: @{error}'); @@ -114,7 +128,10 @@ export function loadPlugin>(config: Config, pluginConfigs: /* eslint new-cap:off */ if (plugin === null || !sanityCheck(plugin)) { - logger.error({ content: pluginId, prefix }, "@{prefix}-@{content} doesn't look like a valid plugin"); + logger.error( + { content: pluginId, prefix }, + "@{prefix}-@{content} doesn't look like a valid plugin" + ); throw Error(`sanity check has failed, "${pluginId}" is not a valid plugin`); } diff --git a/packages/loaders/test/plugin_loader.spec.ts b/packages/loaders/test/plugin_loader.spec.ts index 5d923e349..587f8a654 100644 --- a/packages/loaders/test/plugin_loader.spec.ts +++ b/packages/loaders/test/plugin_loader.spec.ts @@ -46,7 +46,9 @@ describe('plugin loader', () => { return p.authenticate || p.allow_access || p.allow_publish; }); } catch (e) { - expect(e.message).toEqual(`"${relativePath}/invalid-plugin" plugin does not have the right code structure`); + expect(e.message).toEqual( + `"${relativePath}/invalid-plugin" plugin does not have the right code structure` + ); } }); @@ -58,7 +60,9 @@ describe('plugin loader', () => { return plugin.authenticate || plugin.allow_access || plugin.allow_publish; }); } catch (err) { - expect(err.message).toEqual(`sanity check has failed, "${relativePath}/invalid-plugin-sanity" is not a valid plugin`); + expect(err.message).toEqual( + `sanity check has failed, "${relativePath}/invalid-plugin-sanity" is not a valid plugin` + ); } }); @@ -71,7 +75,9 @@ describe('plugin loader', () => { }); } catch (e) { expect(e.message).toMatch('plugin not found'); - expect(e.message.replace(/\\/g, '/')).toMatch('/partials/test-plugin-storage/invalid-package'); + expect(e.message.replace(/\\/g, '/')).toMatch( + '/partials/test-plugin-storage/invalid-package' + ); } }); diff --git a/packages/logger-prettify/src/formatter.ts b/packages/logger-prettify/src/formatter.ts index d38b3380e..cd1b1a877 100644 --- a/packages/logger-prettify/src/formatter.ts +++ b/packages/logger-prettify/src/formatter.ts @@ -62,7 +62,9 @@ function getMessage(debugLevel, msg, sub, templateObjects, hasColors) { const subSystemType = subSystemLevels.color[sub ?? 'default']; if (hasColors) { - const logString = `${levelsColors[debugLevel](pad(debugLevel, LEVEL_VALUE_MAX))}${white(`${subSystemType} ${finalMessage}`)}`; + const logString = `${levelsColors[debugLevel](pad(debugLevel, LEVEL_VALUE_MAX))}${white( + `${subSystemType} ${finalMessage}` + )}`; return padLeft(logString, logString.length + CUSTOM_PAD_LENGTH, ' '); } @@ -71,7 +73,11 @@ function getMessage(debugLevel, msg, sub, templateObjects, hasColors) { return padLeft(logString, logString.length + CUSTOM_PAD_LENGTH, ' '); } -export function printMessage(templateObjects: ObjectTemplate, options: PrettyOptionsExtended, hasColors = true): string { +export function printMessage( + templateObjects: ObjectTemplate, + options: PrettyOptionsExtended, + hasColors = true +): string { const { prettyStamp } = options; const { level, msg, sub } = templateObjects; const debugLevel = calculateLevel(level); diff --git a/packages/logger-prettify/test/formatter.spec.ts b/packages/logger-prettify/test/formatter.spec.ts index 857774244..428966be3 100644 --- a/packages/logger-prettify/test/formatter.spec.ts +++ b/packages/logger-prettify/test/formatter.spec.ts @@ -67,7 +67,8 @@ describe('formatter', () => { status: 200, error: undefined, bytes: { in: 0, out: 150186 }, - msg: "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', bytes: @{bytes.in}/@{bytes.out}", + msg: + "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', bytes: @{bytes.in}/@{bytes.out}", }; expect(printMessage(log, prettyfierOptions)).toMatchSnapshot(); @@ -84,7 +85,9 @@ describe('formatter', () => { err: { type: 'Error', message: 'getaddrinfo ENOTFOUND registry.fake.org', - stack: 'Error: getaddrinfo ENOTFOUND registry.fake.org\n' + ' at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26)', + stack: + 'Error: getaddrinfo ENOTFOUND registry.fake.org\n' + + ' at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26)', errno: -3008, code: 'ENOTFOUND', syscall: 'getaddrinfo', diff --git a/packages/logger/src/logger.ts b/packages/logger/src/logger.ts index b180c4470..15b06ef42 100644 --- a/packages/logger/src/logger.ts +++ b/packages/logger/src/logger.ts @@ -18,7 +18,12 @@ export type LogPlugin = { export type LogType = 'file' | 'stdout'; export type LogFormat = 'json' | 'pretty-timestamped' | 'pretty'; -export function createLogger(options = {}, destination = pino.destination(1), format: LogFormat = DEFAULT_LOG_FORMAT, prettyPrintOptions = {}) { +export function createLogger( + options = {}, + destination = pino.destination(1), + format: LogFormat = DEFAULT_LOG_FORMAT, + prettyPrintOptions = {} +) { if (_.isNil(format)) { format = DEFAULT_LOG_FORMAT; } diff --git a/packages/middleware/package.json b/packages/middleware/package.json index dcc3880a1..316bd4c59 100644 --- a/packages/middleware/package.json +++ b/packages/middleware/package.json @@ -26,10 +26,7 @@ "@verdaccio/dev-commons": "workspace:5.0.0-alpha.0", "@verdaccio/logger": "workspace:5.0.0-alpha.0", "@verdaccio/utils": "workspace:5.0.0-alpha.0", + "@verdaccio/auth": "workspace:5.0.0-alpha.0", "lodash": "4.17.15" - }, - "devDependencies": { - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0" - }, - "gitHead": "7c246ede52ff717707fcae66dd63fc4abd536982" + } } diff --git a/packages/middleware/src/middleware.ts b/packages/middleware/src/middleware.ts index fe11df23c..a2cb9d02b 100644 --- a/packages/middleware/src/middleware.ts +++ b/packages/middleware/src/middleware.ts @@ -8,15 +8,34 @@ import { stringToMD5, ErrorCode, } from '@verdaccio/utils'; -import { API_ERROR, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '@verdaccio/dev-commons'; -import { $ResponseExtend, $RequestExtend, $NextFunctionVer, IAuth } from '@verdaccio/dev-types'; -import { Config, Package, RemoteUser } from '@verdaccio/types'; +import { + API_ERROR, + HEADER_TYPE, + HEADERS, + HTTP_STATUS, + TOKEN_BASIC, + TOKEN_BEARER, +} from '@verdaccio/dev-commons'; + +import { NextFunction, Request, Response } from 'express'; + +import { Config, Package, RemoteUser, Logger } from '@verdaccio/types'; import { logger } from '@verdaccio/logger'; +import { IAuth } from '@verdaccio/auth'; import { VerdaccioError } from '@verdaccio/commons-api'; import { HttpError } from 'http-errors'; +export type $RequestExtend = Request & { remote_user?: any; log: Logger }; +export type $ResponseExtend = Response & { cookies?: any }; +export type $NextFunctionVer = NextFunction & any; + export function match(regexp: RegExp): any { - return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer, value: string): void { + return function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer, + value: string + ): void { if (regexp.exec(value)) { next(); } else { @@ -25,7 +44,11 @@ export function match(regexp: RegExp): any { }; } -export function setSecurityWebHeaders(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { +export function setSecurityWebHeaders( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer +): void { // disable loading in frames (clickjacking, etc.) res.header(HEADERS.FRAMES_OPTIONS, 'deny'); // avoid stablish connections outside of domain @@ -39,7 +62,13 @@ export function setSecurityWebHeaders(req: $RequestExtend, res: $ResponseExtend, // flow: express does not match properly // flow info https://github.com/flowtype/flow-typed/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+express -export function validateName(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer, value: string, name: string): void { +export function validateName( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer, + value: string, + name: string +): void { if (value === '-') { // special case in couchdb usually next('route'); @@ -52,7 +81,13 @@ export function validateName(req: $RequestExtend, res: $ResponseExtend, next: $N // flow: express does not match properly // flow info https://github.com/flowtype/flow-typed/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+express -export function validatePackage(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer, value: string, name: string): void { +export function validatePackage( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer, + value: string, + name: string +): void { if (value === '-') { // special case in couchdb usually next('route'); @@ -66,14 +101,26 @@ export function validatePackage(req: $RequestExtend, res: $ResponseExtend, next: export function media(expect: string | null): any { return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { if (req.headers[HEADER_TYPE.CONTENT_TYPE] !== expect) { - next(ErrorCode.getCode(HTTP_STATUS.UNSUPPORTED_MEDIA, 'wrong content-type, expect: ' + expect + ', got: ' + req.headers[HEADER_TYPE.CONTENT_TYPE])); + next( + ErrorCode.getCode( + HTTP_STATUS.UNSUPPORTED_MEDIA, + 'wrong content-type, expect: ' + + expect + + ', got: ' + + req.headers[HEADER_TYPE.CONTENT_TYPE] + ) + ); } else { next(); } }; } -export function encodeScopePackage(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { +export function encodeScopePackage( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer +): void { if (req.url.indexOf('@') !== -1) { // e.g.: /@org/pkg/1.2.3 -> /@org%2Fpkg/1.2.3, /@org%2Fpkg/1.2.3 -> /@org%2Fpkg/1.2.3 req.url = req.url.replace(/^(\/@[^\/%]+)\/(?!$)/, '$1%2F'); @@ -81,7 +128,11 @@ export function encodeScopePackage(req: $RequestExtend, res: $ResponseExtend, ne next(); } -export function expectJson(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { +export function expectJson( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer +): void { if (!isObject(req.body)) { return next(ErrorCode.getBadRequest("can't parse incoming json")); } @@ -108,11 +159,21 @@ export function allow(auth: IAuth): Function { return function (action: string): Function { return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { req.pause(); - const packageName = req.params.scope ? `@${req.params.scope}/${req.params.package}` : req.params.package; - const packageVersion = req.params.filename ? getVersionFromTarball(req.params.filename) : undefined; + const packageName = req.params.scope + ? `@${req.params.scope}/${req.params.package}` + : req.params.package; + const packageVersion = req.params.filename + ? getVersionFromTarball(req.params.filename) + : undefined; const remote: RemoteUser = req.remote_user; - logger.trace({ action, user: remote?.name }, `[middleware/allow][@{action}] allow for @{user}`); - auth['allow_' + action]({ packageName, packageVersion }, remote, function (error, allowed): void { + logger.trace( + { action, user: remote?.name }, + `[middleware/allow][@{action}] allow for @{user}` + ); + auth['allow_' + action]({ packageName, packageVersion }, remote, function ( + error, + allowed + ): void { req.resume(); if (error) { next(error); @@ -134,7 +195,12 @@ export interface MiddlewareError { export type FinalBody = Package | MiddlewareError | string; -export function final(body: FinalBody, req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { +export function final( + body: FinalBody, + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer +): void { if (res.statusCode === HTTP_STATUS.UNAUTHORIZED && !res.getHeader(HEADERS.WWW_AUTH)) { // they say it's required for 401, so... res.header(HEADERS.WWW_AUTH, `${TOKEN_BASIC}, ${TOKEN_BEARER}`); @@ -155,7 +221,10 @@ export function final(body: FinalBody, req: $RequestExtend, res: $ResponseExtend } // don't send etags with errors - if (!res.statusCode || (res.statusCode >= HTTP_STATUS.OK && res.statusCode < HTTP_STATUS.MULTIPLE_CHOICES)) { + if ( + !res.statusCode || + (res.statusCode >= HTTP_STATUS.OK && res.statusCode < HTTP_STATUS.MULTIPLE_CHOICES) + ) { res.header(HEADERS.ETAG, '"' + stringToMD5(body as string) + '"'); } } else { @@ -178,7 +247,8 @@ export function final(body: FinalBody, req: $RequestExtend, res: $ResponseExtend } // FIXME: deprecated, moved to @verdaccio/dev-commons -export const LOG_STATUS_MESSAGE = "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'"; +export const LOG_STATUS_MESSAGE = + "@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}'"; export const LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`; export const LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`; @@ -274,7 +344,12 @@ export function log(req: $RequestExtend, res: $ResponseExtend, next: $NextFuncti next(); } -export function handleError(err: HttpError, req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { +export function handleError( + err: HttpError, + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer +) { if (_.isError(err)) { if (err.code === 'ECONNABORT' && res.statusCode === HTTP_STATUS.NOT_MODIFIED) { return next(); @@ -292,7 +367,11 @@ export function handleError(err: HttpError, req: $RequestExtend, res: $ResponseE } // Middleware -export function errorReportingMiddleware(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { +export function errorReportingMiddleware( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer +): void { res.locals.report_error = res.locals.report_error || function (err: VerdaccioError): void { diff --git a/packages/mock/package.json b/packages/mock/package.json index e5cffb6fd..fbe223395 100644 --- a/packages/mock/package.json +++ b/packages/mock/package.json @@ -32,7 +32,6 @@ "verdaccio": "^4.8.1" }, "devDependencies": { - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/types": "workspace:*" }, "gitHead": "7c246ede52ff717707fcae66dd63fc4abd536982" diff --git a/packages/mock/src/config.ts b/packages/mock/src/config.ts index ab49479c8..aabf58401 100644 --- a/packages/mock/src/config.ts +++ b/packages/mock/src/config.ts @@ -7,7 +7,9 @@ import { parseConfigFile } from '@verdaccio/utils'; * Override the default.yaml configuration file with any new config provided. */ function configExample(externalConfig, configFile: string = 'default.yaml', location: string = '') { - const locationFile = location ? path.join(location, configFile) : path.join(__dirname, `./config/yaml/${configFile}`); + const locationFile = location + ? path.join(location, configFile) + : path.join(__dirname, `./config/yaml/${configFile}`); const config = parseConfigFile(locationFile); return _.assign({}, _.cloneDeep(config), externalConfig); diff --git a/packages/mock/src/mock-api.ts b/packages/mock/src/mock-api.ts index f5eb4445a..f89aab323 100644 --- a/packages/mock/src/mock-api.ts +++ b/packages/mock/src/mock-api.ts @@ -1,7 +1,14 @@ import _ from 'lodash'; import request from 'supertest'; -import { DIST_TAGS, LATEST, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BEARER } from '@verdaccio/dev-commons'; +import { + DIST_TAGS, + LATEST, + HEADER_TYPE, + HEADERS, + HTTP_STATUS, + TOKEN_BEARER, +} from '@verdaccio/dev-commons'; import { buildToken, encodeScopedUri } from '@verdaccio/utils'; import { generateRandomHexString } from '@verdaccio/utils'; import { Package } from '@verdaccio/types'; @@ -29,9 +36,17 @@ export function getTaggedVersionFromPackage(pkg, pkgName, tag: string = LATEST, return latestPkg; } -export function putPackage(request: any, pkgName: string, publishMetadata: Package, token?: string): Promise { +export function putPackage( + request: any, + pkgName: string, + publishMetadata: Package, + token?: string +): Promise { return new Promise((resolve) => { - const put = request.put(pkgName).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON).send(JSON.stringify(publishMetadata)); + const put = request + .put(pkgName) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send(JSON.stringify(publishMetadata)); if (_.isEmpty(token) === false) { expect(token).toBeDefined(); @@ -50,7 +65,9 @@ export function putPackage(request: any, pkgName: string, publishMetadata: Packa export function deletePackage(request: any, pkgName: string, token?: string): Promise { return new Promise((resolve) => { - const del = request.put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); + const del = request + .put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); if (_.isNil(token) === false) { del.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)); @@ -65,7 +82,12 @@ export function deletePackage(request: any, pkgName: string, token?: string): Pr }); } -export function getPackage(request: any, token: string, pkgName: string, statusCode: number = HTTP_STATUS.OK): Promise { +export function getPackage( + request: any, + token: string, + pkgName: string, + statusCode: number = HTTP_STATUS.OK +): Promise { return new Promise((resolve) => { const getRequest = request.get(`/${pkgName}`); @@ -82,7 +104,13 @@ export function getPackage(request: any, token: string, pkgName: string, statusC }); } -export function loginUserToken(request: any, user: string, credentials: any, token: string, statusCode: number = HTTP_STATUS.CREATED): Promise { +export function loginUserToken( + request: any, + user: string, + credentials: any, + token: string, + statusCode: number = HTTP_STATUS.CREATED +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -97,7 +125,12 @@ export function loginUserToken(request: any, user: string, credentials: any, tok }); } -export function addUser(request: any, user: string, credentials: any, statusCode: number = HTTP_STATUS.CREATED): Promise { +export function addUser( + request: any, + user: string, + credentials: any, + statusCode: number = HTTP_STATUS.CREATED +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -124,7 +157,11 @@ export async function getNewToken(request: any, credentials: any): Promise { +export function getProfile( + request: any, + token: string, + statusCode: number = HTTP_STATUS.OK +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -138,7 +175,12 @@ export function getProfile(request: any, token: string, statusCode: number = HTT }); } -export function postProfile(request: any, body: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { +export function postProfile( + request: any, + body: any, + token: string, + statusCode: number = HTTP_STATUS.OK +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -153,7 +195,13 @@ export function postProfile(request: any, body: any, token: string, statusCode: }); } -export async function fetchPackageByVersionAndTag(app, encodedPkgName, pkgName, version, tag = 'latest') { +export async function fetchPackageByVersionAndTag( + app, + encodedPkgName, + pkgName, + version, + tag = 'latest' +) { // we retrieve the package to verify const [err, resp] = await getPackage(request(app), '', encodedPkgName); @@ -170,7 +218,12 @@ export async function isExistPackage(app, packageName) { } export async function verifyPackageVersionDoesExist(app, packageName, version, token?: string) { - const [, res] = await getPackage(request(app), token as string, encodeScopedUri(packageName), HTTP_STATUS.OK); + const [, res] = await getPackage( + request(app), + token as string, + encodeScopedUri(packageName), + HTTP_STATUS.OK + ); const { versions } = res.body; const versionsKeys = Object.keys(versions); diff --git a/packages/mock/src/mock.ts b/packages/mock/src/mock.ts index 52c338590..f8160879e 100644 --- a/packages/mock/src/mock.ts +++ b/packages/mock/src/mock.ts @@ -81,7 +81,12 @@ export function mockServer(port: number, options: MockRegistryOptions = {}) { fs.copyFileSync(finalOptions.configPath!, tempConfigFile); fsExtra.copySync(finalOptions.storePath!, storePath); - const verdaccioConfig = new VerdaccioConfig(storePath, tempConfigFile, `http://${DOMAIN_SERVERS}:${port}/`, port); + const verdaccioConfig = new VerdaccioConfig( + storePath, + tempConfigFile, + `http://${DOMAIN_SERVERS}:${port}/`, + port + ); const server: IServerBridge = new Server(verdaccioConfig.domainPath); return new VerdaccioProcess(verdaccioConfig, server, finalOptions.silence, finalOptions.debug); diff --git a/packages/mock/src/server.ts b/packages/mock/src/server.ts index bd645f832..3c1d01d75 100644 --- a/packages/mock/src/server.ts +++ b/packages/mock/src/server.ts @@ -147,7 +147,12 @@ export default class Server implements IServerBridge { }).send(JSON.stringify(version)); } - public putTarballIncomplete(pkgName: string, filename: string, data: any, headerContentSize: number): Promise { + public putTarballIncomplete( + pkgName: string, + filename: string, + data: any, + headerContentSize: number + ): Promise { const promise = this.request({ uri: `/${encodeURIComponent(pkgName)}/-/${encodeURIComponent(filename)}/whatever`, method: 'PUT', @@ -183,7 +188,9 @@ export default class Server implements IServerBridge { } public addPackage(name: string) { - return this.putPackage(name, getPackage(name)).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); + return this.putPackage(name, getPackage(name)) + .status(HTTP_STATUS.CREATED) + .body_ok(API_MESSAGE.PKG_CREATED); } public whoami() { diff --git a/packages/mock/src/server_process.ts b/packages/mock/src/server_process.ts index 275921051..102503341 100644 --- a/packages/mock/src/server_process.ts +++ b/packages/mock/src/server_process.ts @@ -14,7 +14,12 @@ export default class VerdaccioProcess implements IServerProcess { private isDebug: boolean; private silence: boolean; - public constructor(config: IVerdaccioConfig, bridge: IServerBridge, silence = true, isDebug = false) { + public constructor( + config: IVerdaccioConfig, + bridge: IServerBridge, + silence = true, + isDebug = false + ) { this.config = config; this.bridge = bridge; this.silence = silence; diff --git a/packages/mock/src/utils-test.ts b/packages/mock/src/utils-test.ts index 4924d66ba..70c1479db 100644 --- a/packages/mock/src/utils-test.ts +++ b/packages/mock/src/utils-test.ts @@ -11,7 +11,11 @@ export function generateRamdonStorage() { return path.join(tempRoot, tempStorage); } -export function generateNewVersion(pkgName: string, version: string, shashum = '238e7641e59508dc9c20eb4ad37a8aa57ab777b4'): Version { +export function generateNewVersion( + pkgName: string, + version: string, + shashum = '238e7641e59508dc9c20eb4ad37a8aa57ab777b4' +): Version { // $FlowFixMe return { name: pkgName, @@ -30,7 +34,8 @@ export function generateNewVersion(pkgName: string, version: string, shashum = ' name: 'Foo', }, dist: { - integrity: 'sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4QdwXARU7dYWPnrwhGg==', + integrity: + 'sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4QdwXARU7dYWPnrwhGg==', shasum: shashum, tarball: `http:\/\/localhost:4873\/${pkgName}\/-\/${pkgName}-${version}.tgz`, }, diff --git a/packages/node-api/src/bootstrap.d.ts b/packages/node-api/src/bootstrap.d.ts index e19e54ed1..e494fe2e3 100644 --- a/packages/node-api/src/bootstrap.d.ts +++ b/packages/node-api/src/bootstrap.d.ts @@ -8,6 +8,18 @@ import { Callback } from '@verdaccio/types'; * @param {String} pkgVersion * @param {String} pkgName */ -declare function startVerdaccio(config: any, cliListen: string, configPath: string, pkgVersion: string, pkgName: string, callback: Callback): void; -declare function listenDefaultCallback(webServer: Application, addr: any, pkgName: string, pkgVersion: string): void; +declare function startVerdaccio( + config: any, + cliListen: string, + configPath: string, + pkgVersion: string, + pkgName: string, + callback: Callback +): void; +declare function listenDefaultCallback( + webServer: Application, + addr: any, + pkgName: string, + pkgVersion: string +): void; export { startVerdaccio, listenDefaultCallback }; diff --git a/packages/node-api/src/bootstrap.ts b/packages/node-api/src/bootstrap.ts index b86da7668..d220ff1e6 100644 --- a/packages/node-api/src/bootstrap.ts +++ b/packages/node-api/src/bootstrap.ts @@ -14,7 +14,15 @@ import { logger } from '@verdaccio/logger'; import { getListListenAddresses, resolveConfigPath } from './cli-utils'; import { displayExperimentsInfoBox } from './experiments'; -function launchServer(app, addr, config, configPath: string, pkgVersion: string, pkgName: string, callback: Callback): void { +function launchServer( + app, + addr, + config, + configPath: string, + pkgVersion: string, + pkgName: string, + callback: Callback +): void { let webServer; if (addr.proto === 'https') { webServer = handleHTTPS(app, configPath, config); @@ -22,7 +30,11 @@ function launchServer(app, addr, config, configPath: string, pkgVersion: string, // http webServer = http.createServer(app); } - if (config.server && typeof config.server.keepAliveTimeout !== 'undefined' && config.server.keepAliveTimeout !== 'null') { + if ( + config.server && + typeof config.server.keepAliveTimeout !== 'undefined' && + config.server.keepAliveTimeout !== 'null' + ) { // library definition for node is not up to date (doesn't contain recent 8.0 changes) webServer.keepAliveTimeout = config.server.keepAliveTimeout * 1000; } @@ -39,7 +51,14 @@ function launchServer(app, addr, config, configPath: string, pkgVersion: string, * @param {String} pkgVersion * @param {String} pkgName */ -function startVerdaccio(config: any, cliListen: string, configPath: string, pkgVersion: string, pkgName: string, callback: Callback): void { +function startVerdaccio( + config: any, + cliListen: string, + configPath: string, + pkgVersion: string, + pkgName: string, + callback: Callback +): void { if (isObject(config) === false) { throw new Error(API_ERROR.CONFIG_BAD_FORMAT); } @@ -50,7 +69,9 @@ function startVerdaccio(config: any, cliListen: string, configPath: string, pkgV displayExperimentsInfoBox(config.experiments); } - addresses.forEach((addr) => launchServer(app, addr, config, configPath, pkgVersion, pkgName, callback)); + addresses.forEach((addr) => + launchServer(app, addr, config, configPath, pkgVersion, pkgName, callback) + ); }); } @@ -71,7 +92,10 @@ function logHTTPSWarning(storageLocation) { // commands are borrowed from node.js docs 'To quickly create self-signed certificate, use:', ' $ openssl genrsa -out ' + resolveConfigPath(storageLocation, keyPem) + ' 2048', - ' $ openssl req -new -sha256 -key ' + resolveConfigPath(storageLocation, keyPem) + ' -out ' + resolveConfigPath(storageLocation, csrPem), + ' $ openssl req -new -sha256 -key ' + + resolveConfigPath(storageLocation, keyPem) + + ' -out ' + + resolveConfigPath(storageLocation, csrPem), ' $ openssl x509 -req -in ' + resolveConfigPath(storageLocation, csrPem) + ' -signkey ' + @@ -126,7 +150,12 @@ function handleHTTPS(app: Application, configPath: string, config: ConfigWithHtt } } -function listenDefaultCallback(webServer: Application, addr: any, pkgName: string, pkgVersion: string): void { +function listenDefaultCallback( + webServer: Application, + addr: any, + pkgName: string, + pkgVersion: string +): void { webServer .listen(addr.port || addr.path, addr.host, (): void => { // send a message for tests diff --git a/packages/node-api/src/cli-utils.ts b/packages/node-api/src/cli-utils.ts index 73ddd3996..2d7f4c4e7 100644 --- a/packages/node-api/src/cli-utils.ts +++ b/packages/node-api/src/cli-utils.ts @@ -48,7 +48,9 @@ export function getListListenAddresses(argListen: string, configListen: any): an if (!parsedAddr) { logger.logger.warn( { addr: addr }, - 'invalid address - @{addr}, we expect a port (e.g. "4873"),' + ' host:port (e.g. "localhost:4873") or full url' + ' (e.g. "http://localhost:4873/")' + 'invalid address - @{addr}, we expect a port (e.g. "4873"),' + + ' host:port (e.g. "localhost:4873") or full url' + + ' (e.g. "http://localhost:4873/")' ); } diff --git a/packages/node-api/src/experiments.ts b/packages/node-api/src/experiments.ts index ed3c8ce0f..6cb130808 100644 --- a/packages/node-api/src/experiments.ts +++ b/packages/node-api/src/experiments.ts @@ -3,9 +3,13 @@ const logger = require('@verdaccio/logger'); export function displayExperimentsInfoBox(experiments) { const experimentList = Object.keys(experiments); if (experimentList.length >= 1) { - logger.logger.warn('⚠️ experiments are enabled, we recommend do not use experiments in production, comment out this section to disable it'); + logger.logger.warn( + '⚠️ experiments are enabled, we recommend do not use experiments in production, comment out this section to disable it' + ); experimentList.forEach((experiment) => { - logger.logger.warn(` - support for ${experiment} ${experiments[experiment] ? 'is enabled' : ' is disabled'}`); + logger.logger.warn( + ` - support for ${experiment} ${experiments[experiment] ? 'is enabled' : ' is disabled'}` + ); }); } } diff --git a/packages/node-api/src/https.ts b/packages/node-api/src/https.ts index 2d4b16f24..9cdfe3050 100644 --- a/packages/node-api/src/https.ts +++ b/packages/node-api/src/https.ts @@ -15,7 +15,10 @@ export function logHTTPSWarning(storageLocation) { // commands are borrowed from node.js docs 'To quickly create self-signed certificate, use:', ' $ openssl genrsa -out ' + resolveConfigPath(storageLocation, keyPem) + ' 2048', - ' $ openssl req -new -sha256 -key ' + resolveConfigPath(storageLocation, keyPem) + ' -out ' + resolveConfigPath(storageLocation, csrPem), + ' $ openssl req -new -sha256 -key ' + + resolveConfigPath(storageLocation, keyPem) + + ' -out ' + + resolveConfigPath(storageLocation, csrPem), ' $ openssl x509 -req -in ' + resolveConfigPath(storageLocation, csrPem) + ' -signkey ' + diff --git a/packages/node-api/test/node-api.spec.ts b/packages/node-api/test/node-api.spec.ts index afef69230..93dde38c4 100644 --- a/packages/node-api/test/node-api.spec.ts +++ b/packages/node-api/test/node-api.spec.ts @@ -35,18 +35,25 @@ describe('startServer via API', () => { const version = '1.0.0'; const port = '6000'; - await startVerdaccio(configExample(), port, store, version, serverName, (webServer, addrs, pkgName, pkgVersion) => { - expect(webServer).toBeDefined(); - expect(addrs).toBeDefined(); - expect(addrs.proto).toBe(DEFAULT_PROTOCOL); - expect(addrs.host).toBe(DEFAULT_DOMAIN); - expect(addrs.port).toBe(port); - expect(pkgName).toBeDefined(); - expect(pkgVersion).toBeDefined(); - expect(pkgVersion).toBe(version); - expect(pkgName).toBe(serverName); - done(); - }); + await startVerdaccio( + configExample(), + port, + store, + version, + serverName, + (webServer, addrs, pkgName, pkgVersion) => { + expect(webServer).toBeDefined(); + expect(addrs).toBeDefined(); + expect(addrs.proto).toBe(DEFAULT_PROTOCOL); + expect(addrs.host).toBe(DEFAULT_DOMAIN); + expect(addrs.port).toBe(port); + expect(pkgName).toBeDefined(); + expect(pkgVersion).toBeDefined(); + expect(pkgVersion).toBe(version); + expect(pkgName).toBe(serverName); + done(); + } + ); }); test('should set keepAliveTimeout to 0 seconds', async (done) => { diff --git a/packages/proxy/package.json b/packages/proxy/package.json index a79a703b7..2a655604b 100644 --- a/packages/proxy/package.json +++ b/packages/proxy/package.json @@ -33,7 +33,6 @@ "request": "2.87.0" }, "devDependencies": { - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/types": "workspace:*" }, "gitHead": "7c246ede52ff717707fcae66dd63fc4abd536982" diff --git a/packages/proxy/src/up-storage.ts b/packages/proxy/src/up-storage.ts index f1ed30f76..141769640 100644 --- a/packages/proxy/src/up-storage.ts +++ b/packages/proxy/src/up-storage.ts @@ -6,9 +6,25 @@ import _ from 'lodash'; import request from 'request'; import { parseInterval, isObject, ErrorCode, buildToken } from '@verdaccio/utils'; import { ReadTarball } from '@verdaccio/streams'; -import { ERROR_CODE, TOKEN_BASIC, TOKEN_BEARER, HEADERS, HTTP_STATUS, API_ERROR, HEADER_TYPE, CHARACTER_ENCODING } from '@verdaccio/dev-commons'; -import { Config, Callback, Headers, Logger, Package } from '@verdaccio/types'; -import { IProxy, UpLinkConfLocal } from '@verdaccio/dev-types'; +import { + ERROR_CODE, + TOKEN_BASIC, + TOKEN_BEARER, + HEADERS, + HTTP_STATUS, + API_ERROR, + HEADER_TYPE, + CHARACTER_ENCODING, +} from '@verdaccio/dev-commons'; +import { + Config, + Callback, + Headers, + Logger, + UpLinkConf, + Package, + IReadTarball, +} from '@verdaccio/types'; const LoggerApi = require('@verdaccio/logger'); const encode = function (thing): string { @@ -25,6 +41,33 @@ const setConfig = (config, key, def): string => { return _.isNil(config[key]) === false ? config[key] : def; }; +export type UpLinkConfLocal = UpLinkConf & { + no_proxy?: string; +}; + +export interface ProxyList { + [key: string]: IProxy; +} + +export interface IProxy { + config: UpLinkConfLocal; + failed_requests: number; + userAgent: string; + ca?: string | void; + logger: Logger; + server_id: string; + url: any; + maxage: number; + timeout: number; + max_fails: number; + fail_timeout: number; + upname: string; + fetchTarball(url: string): IReadTarball; + isUplinkValid(url: string): boolean; + search(options: any); + getRemoteMetadata(name: string, options: any, callback: Callback): void; +} + /** * Implements Storage interface * (same for storage.js, local-storage.js, up-storage.js) @@ -401,8 +444,11 @@ class ProxyStorage implements IProxy { public isUplinkValid(url: string): boolean { // $FlowFixMe const urlParsed: UrlWithStringQuery = URL.parse(url); - const isHTTPS = (urlDomainParsed: URL): boolean => urlDomainParsed.protocol === 'https:' && (urlParsed.port === null || urlParsed.port === '443'); - const getHost = (urlDomainParsed): boolean => (isHTTPS(urlDomainParsed) ? urlDomainParsed.hostname : urlDomainParsed.host); + const isHTTPS = (urlDomainParsed: URL): boolean => + urlDomainParsed.protocol === 'https:' && + (urlParsed.port === null || urlParsed.port === '443'); + const getHost = (urlDomainParsed): boolean => + isHTTPS(urlDomainParsed) ? urlDomainParsed.hostname : urlDomainParsed.host; const isMatchProtocol: boolean = urlParsed.protocol === this.url.protocol; const isMatchHost: boolean = getHost(urlParsed) === getHost(this.url); // @ts-ignore @@ -439,7 +485,9 @@ class ProxyStorage implements IProxy { return callback(ErrorCode.getNotFound(API_ERROR.NOT_PACKAGE_UPLINK)); } if (!(res.statusCode >= HTTP_STATUS.OK && res.statusCode < HTTP_STATUS.MULTIPLE_CHOICES)) { - const error = ErrorCode.getInternalError(`${API_ERROR.BAD_STATUS_CODE}: ${res.statusCode}`); + const error = ErrorCode.getInternalError( + `${API_ERROR.BAD_STATUS_CODE}: ${res.statusCode}` + ); // $FlowFixMe error.remoteStatus = res.statusCode; return callback(error); @@ -473,7 +521,10 @@ class ProxyStorage implements IProxy { return stream.emit('error', ErrorCode.getNotFound(API_ERROR.NOT_FILE_UPLINK)); } if (!(res.statusCode >= HTTP_STATUS.OK && res.statusCode < HTTP_STATUS.MULTIPLE_CHOICES)) { - return stream.emit('error', ErrorCode.getInternalError(`bad uplink status code: ${res.statusCode}`)); + return stream.emit( + 'error', + ErrorCode.getInternalError(`bad uplink status code: ${res.statusCode}`) + ); } if (res.headers[HEADER_TYPE.CONTENT_LENGTH]) { expected_length = res.headers[HEADER_TYPE.CONTENT_LENGTH]; @@ -523,7 +574,10 @@ class ProxyStorage implements IProxy { requestStream.on('response', (res): void => { if (!String(res.statusCode).match(/^2\d\d$/)) { - return transformStream.emit('error', ErrorCode.getInternalError(`bad status code ${res.statusCode} from uplink`)); + return transformStream.emit( + 'error', + ErrorCode.getInternalError(`bad status code ${res.statusCode} from uplink`) + ); } // See https://github.com/request/request#requestoptions-callback @@ -572,7 +626,9 @@ class ProxyStorage implements IProxy { // FIXME: proxy logic is odd, something is wrong here. // @ts-ignore if (!this.proxy) { - headers['X-Forwarded-For'] = (req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'] + ', ' : '') + req.connection.remoteAddress; + headers['X-Forwarded-For'] = + (req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'] + ', ' : '') + + req.connection.remoteAddress; } } @@ -622,7 +678,10 @@ class ProxyStorage implements IProxy { * @private */ private _ifRequestFailure(): boolean { - return this.failed_requests >= this.max_fails && Math.abs(Date.now() - (this.last_request_time as number)) < this.fail_timeout; + return ( + this.failed_requests >= this.max_fails && + Math.abs(Date.now() - (this.last_request_time as number)) < this.fail_timeout + ); } /** @@ -632,7 +691,12 @@ class ProxyStorage implements IProxy { * @param {*} mainconfig * @param {*} isHTTPS */ - private _setupProxy(hostname: string, config: UpLinkConfLocal, mainconfig: Config, isHTTPS: boolean): void { + private _setupProxy( + hostname: string, + config: UpLinkConfLocal, + mainconfig: Config, + isHTTPS: boolean + ): void { let noProxyList; const proxy_key: string = isHTTPS ? 'https_proxy' : 'http_proxy'; @@ -667,7 +731,10 @@ class ProxyStorage implements IProxy { } if (hostname.lastIndexOf(noProxyItem) === hostname.length - noProxyItem.length) { if (this.proxy) { - this.logger.debug({ url: this.url.href, rule: noProxyItem }, 'not using proxy for @{url}, excluded by @{rule} rule'); + this.logger.debug( + { url: this.url.href, rule: noProxyItem }, + 'not using proxy for @{url}, excluded by @{rule} rule' + ); // @ts-ignore this.proxy = false; } @@ -680,7 +747,10 @@ class ProxyStorage implements IProxy { if (_.isString(this.proxy) === false) { delete this.proxy; } else { - this.logger.debug({ url: this.url.href, proxy: this.proxy }, 'using proxy @{proxy} for @{url}'); + this.logger.debug( + { url: this.url.href, proxy: this.proxy }, + 'using proxy @{proxy} for @{url}' + ); } } } diff --git a/packages/proxy/src/uplink-util.ts b/packages/proxy/src/uplink-util.ts index 51d06b566..623e85613 100644 --- a/packages/proxy/src/uplink-util.ts +++ b/packages/proxy/src/uplink-util.ts @@ -1,7 +1,6 @@ import { Versions, Config } from '@verdaccio/types'; -import { IProxy, ProxyList } from '@verdaccio/dev-types'; -import { ProxyStorage } from './up-storage'; +import { ProxyStorage, IProxy, ProxyList } from './up-storage'; /** * Set up the Up Storage for each link. diff --git a/packages/proxy/test/headers.auth.spec.ts b/packages/proxy/test/headers.auth.spec.ts index d1033dc41..5a461a5bc 100644 --- a/packages/proxy/test/headers.auth.spec.ts +++ b/packages/proxy/test/headers.auth.spec.ts @@ -1,6 +1,12 @@ import { buildToken } from '@verdaccio/utils'; -import { ERROR_CODE, TOKEN_BASIC, TOKEN_BEARER, DEFAULT_REGISTRY, HEADERS } from '@verdaccio/dev-commons'; +import { + ERROR_CODE, + TOKEN_BASIC, + TOKEN_BEARER, + DEFAULT_REGISTRY, + HEADERS, +} from '@verdaccio/dev-commons'; import { setup } from '@verdaccio/logger'; import { ProxyStorage } from '../src/up-storage'; diff --git a/packages/server/package.json b/packages/server/package.json index eeae1f26b..5a50860fd 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -32,7 +32,6 @@ }, "devDependencies": { "@verdaccio/commons-api": "workspace:*", - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/mock": "workspace:5.0.0-alpha.0", "@verdaccio/proxy": "workspace:5.0.0-alpha.0", "http-errors": "1.7.3", diff --git a/packages/server/src/debug/index.ts b/packages/server/src/debug/index.ts index 75a154a0e..76c9ff5b8 100644 --- a/packages/server/src/debug/index.ts +++ b/packages/server/src/debug/index.ts @@ -1,10 +1,14 @@ import _ from 'lodash'; import { Application } from 'express'; -import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from '@verdaccio/dev-types'; +import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from '../../types/custom'; export default (app: Application, selfPath: string): void => { // Hook for tests only - app.get('/-/_debug', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + app.get('/-/_debug', function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { const doGarbabeCollector = _.isNil(global.gc) === false; if (doGarbabeCollector) { diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index 0ddb59c8c..1abce90dd 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -14,10 +14,12 @@ import { Config as AppConfig } from '@verdaccio/config'; import { webAPI, renderWebMiddleware } from '@verdaccio/web'; -import { $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler, IAuth } from '@verdaccio/dev-types'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; import { Config as IConfig, IPluginMiddleware, IPluginStorageFilter } from '@verdaccio/types'; import { setup, logger } from '@verdaccio/logger'; import { log, final, errorReportingMiddleware } from '@verdaccio/middleware'; +import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from '../types/custom'; import hookDebug from './debug'; @@ -39,7 +41,11 @@ const defineAPI = function (config: IConfig, storage: IStorageHandler): any { app.use(compression()); - app.get('/favicon.ico', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + app.get('/favicon.ico', function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { req.url = '/-/static/favicon.png'; next(); }); @@ -55,14 +61,20 @@ const defineAPI = function (config: IConfig, storage: IStorageHandler): any { logger: logger, }; - const plugins: IPluginMiddleware[] = loadPlugin(config, config.middlewares, plugin_params, function (plugin: IPluginMiddleware) { - return plugin.register_middlewares; - }); + const plugins: IPluginMiddleware[] = loadPlugin( + config, + config.middlewares, + plugin_params, + function (plugin: IPluginMiddleware) { + return plugin.register_middlewares; + } + ); plugins.forEach((plugin: IPluginMiddleware) => { plugin.register_middlewares(app, auth, storage); }); // For npm request + // @ts-ignore app.use(apiEndpoint(config, auth, storage)); // For WebUI & WebUI API @@ -80,7 +92,12 @@ const defineAPI = function (config: IConfig, storage: IStorageHandler): any { next(ErrorCode.getNotFound(API_ERROR.FILE_NOT_FOUND)); }); - app.use(function (err: HttpError, req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) { + app.use(function ( + err: HttpError, + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ) { if (_.isError(err)) { if (err.code === 'ECONNABORT' && res.statusCode === HTTP_STATUS.NOT_MODIFIED) { return next(); @@ -110,7 +127,12 @@ export default (async function (configHash: any): Promise { config: config, logger: logger, }; - const filters = loadPlugin(config, config.filters || {}, plugin_params, (plugin: IPluginStorageFilter) => plugin.filter_metadata); + const filters = loadPlugin( + config, + config.filters || {}, + plugin_params, + (plugin: IPluginStorageFilter) => plugin.filter_metadata + ); const storage: IStorageHandler = new Storage(config); // waits until init calls have been initialized await storage.init(config, filters); diff --git a/packages/server/test/api/helpers/publish-api.js b/packages/server/test/api/helpers/publish-api.js index 099fc4124..b0cb4a890 100644 --- a/packages/server/test/api/helpers/publish-api.js +++ b/packages/server/test/api/helpers/publish-api.js @@ -30,7 +30,8 @@ const json = { _nodeVersion: '8.7.0', _npmUser: {}, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', tarball: 'http://localhost:5555/@scope/pk1-test/-/@scope/pk1-test-1.0.6.tgz', }, diff --git a/packages/server/test/api/helpers/utils.ts b/packages/server/test/api/helpers/utils.ts index 225c21d36..4f83ed241 100644 --- a/packages/server/test/api/helpers/utils.ts +++ b/packages/server/test/api/helpers/utils.ts @@ -26,7 +26,8 @@ export function generateVersion(pkgName, version) { name: 'foo', }, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, }, @@ -39,7 +40,10 @@ export function generateVersion(pkgName, version) { * @param pkgName * @param _versions */ -export function generatePackageUnpublish(pkgName: string, _versions: string[] = ['1.0.0']): Package { +export function generatePackageUnpublish( + pkgName: string, + _versions: string[] = ['1.0.0'] +): Package { const latest: string = _versions[_versions.length - 1]; const versions = _versions.reduce((cat, version) => { cat[version] = generateVersion(pkgName, version); @@ -102,7 +106,8 @@ export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Pac name: 'foo', }, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, }, @@ -120,7 +125,11 @@ export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Pac }; } -export function generateDeprecateMetadata(pkgName: string, version = '1.0.0', deprecated: string = ''): Package { +export function generateDeprecateMetadata( + pkgName: string, + version = '1.0.0', + deprecated: string = '' +): Package { const res = { ...generatePackageMetadata(pkgName, version), _attachments: {}, diff --git a/packages/server/test/api/index.spec.ts b/packages/server/test/api/index.spec.ts index f4b942f43..06e58c5a4 100644 --- a/packages/server/test/api/index.spec.ts +++ b/packages/server/test/api/index.spec.ts @@ -2,7 +2,13 @@ import path from 'path'; import request from 'supertest'; import _ from 'lodash'; -import { HEADERS, HTTP_STATUS, HEADER_TYPE, API_MESSAGE, TOKEN_BEARER } from '@verdaccio/dev-commons'; +import { + HEADERS, + HTTP_STATUS, + HEADER_TYPE, + API_MESSAGE, + TOKEN_BEARER, +} from '@verdaccio/dev-commons'; import { buildToken, encodeScopedUri } from '@verdaccio/utils'; import { setup, logger } from '@verdaccio/logger'; @@ -21,7 +27,13 @@ import { import endPointAPI from '../../src'; import publishMetadata from './helpers/publish-api'; -import { generateDeprecateMetadata, generatePackageMetadata, generatePackageUnpublish, generateStarMedatada, generateVersion } from './helpers/utils'; +import { + generateDeprecateMetadata, + generatePackageMetadata, + generatePackageUnpublish, + generateStarMedatada, + generateVersion, +} from './helpers/utils'; setup([]); @@ -91,7 +103,9 @@ describe('endpoint unit test', () => { .expect(HTTP_STATUS.FORBIDDEN) .end(function (err, res) { expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(/authorization required to access package auth-package/); + expect(res.body.error).toMatch( + /authorization required to access package auth-package/ + ); done(); }); }); @@ -104,7 +118,9 @@ describe('endpoint unit test', () => { .expect(HTTP_STATUS.FORBIDDEN) .end(function (err, res) { expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(/authorization required to access package auth-package/); + expect(res.body.error).toMatch( + /authorization required to access package auth-package/ + ); done(); }); }); @@ -117,7 +133,9 @@ describe('endpoint unit test', () => { .expect(HTTP_STATUS.FORBIDDEN) .end(function (err, res) { expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(/authorization required to access package auth-package/); + expect(res.body.error).toMatch( + /authorization required to access package auth-package/ + ); done(); }); }); @@ -470,14 +488,24 @@ describe('endpoint unit test', () => { } const newVersion = '2.0.1'; - const [newErr] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, generatePackageMetadata(pkgName, newVersion), token); + const [newErr] = await putPackage( + request(app), + `/${encodeScopedUri(pkgName)}`, + generatePackageMetadata(pkgName, newVersion), + token + ); if (newErr) { expect(newErr).toBeNull(); return done(newErr); } const deletePayload = generatePackageUnpublish(pkgName, ['2.0.0']); - const [err2, res2] = await putPackage(request(app), generateUnPublishURI(pkgName), deletePayload, token); + const [err2, res2] = await putPackage( + request(app), + generateUnPublishURI(pkgName), + deletePayload, + token + ); expect(err2).toBeNull(); expect(res2.body.ok).toMatch(API_MESSAGE.PKG_CHANGED); @@ -526,17 +554,29 @@ describe('endpoint unit test', () => { const newVersion = '1.0.0'; const token = await getNewToken(request(app), credentials); - const [newErr] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, generatePackageMetadata(pkgName, newVersion), token); + const [newErr] = await putPackage( + request(app), + `/${encodeScopedUri(pkgName)}`, + generatePackageMetadata(pkgName, newVersion), + token + ); if (newErr) { expect(newErr).toBeNull(); return done(newErr); } const deletePayload = generatePackageUnpublish(pkgName, ['2.0.0']); - const [err2, res2] = await putPackage(request(app), generateUnPublishURI(pkgName), deletePayload, token); + const [err2, res2] = await putPackage( + request(app), + generateUnPublishURI(pkgName), + deletePayload, + token + ); expect(err2).not.toBeNull(); - expect(res2.body.error).toMatch(/user jota_unpublish_fail is not allowed to unpublish package non-unpublish/); + expect(res2.body.error).toMatch( + /user jota_unpublish_fail is not allowed to unpublish package non-unpublish/ + ); done(); }); @@ -562,10 +602,17 @@ describe('endpoint unit test', () => { const newVersion = '1.0.0'; const token = await getNewToken(request(app), credentials); - const [newErr, resp] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, generatePackageMetadata(pkgName, newVersion), token); + const [newErr, resp] = await putPackage( + request(app), + `/${encodeScopedUri(pkgName)}`, + generatePackageMetadata(pkgName, newVersion), + token + ); expect(newErr).not.toBeNull(); - expect(resp.body.error).toMatch(/user jota_only_unpublish_fail is not allowed to publish package only-unpublish/); + expect(resp.body.error).toMatch( + /user jota_only_unpublish_fail is not allowed to publish package only-unpublish/ + ); done(); }); }); @@ -741,7 +788,12 @@ describe('endpoint unit test', () => { let token = ''; beforeAll(async (done) => { token = await getNewToken(request(app), credentials); - await putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName, version), token); + await putPackage( + request(app), + `/${pkgName}`, + generatePackageMetadata(pkgName, version), + token + ); done(); }); @@ -775,20 +827,39 @@ describe('endpoint unit test', () => { let credentials = { name: 'only_publish', password: 'secretPass' }; let token = await getNewToken(request(app), credentials); const pkg = generateDeprecateMetadata(pkgName, version, 'get deprecated'); - const [err, res] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, pkg, token); + const [err, res] = await putPackage( + request(app), + `/${encodeScopedUri(pkgName)}`, + pkg, + token + ); expect(err).not.toBeNull(); expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(/user only_publish is not allowed to unpublish package @scope\/deprecate/); + expect(res.body.error).toMatch( + /user only_publish is not allowed to unpublish package @scope\/deprecate/ + ); credentials = { name: 'only_unpublish', password: 'secretPass' }; token = await getNewToken(request(app), credentials); - const [err2, res2] = await putPackage(request(app), `/${encodeScopedUri(pkgName)}`, pkg, token); + const [err2, res2] = await putPackage( + request(app), + `/${encodeScopedUri(pkgName)}`, + pkg, + token + ); expect(err2).not.toBeNull(); expect(res2.body.error).toBeDefined(); - expect(res2.body.error).toMatch(/user only_unpublish is not allowed to publish package @scope\/deprecate/); + expect(res2.body.error).toMatch( + /user only_unpublish is not allowed to publish package @scope\/deprecate/ + ); }); test('should deprecate multiple packages', async (done) => { - await putPackage(request(app), `/${pkgName}`, generatePackageMetadata(pkgName, '1.0.1'), token); + await putPackage( + request(app), + `/${pkgName}`, + generatePackageMetadata(pkgName, '1.0.1'), + token + ); const pkg = generateDeprecateMetadata(pkgName, version, 'get deprecated'); pkg.versions['1.0.1'] = { ...generateVersion(pkgName, '1.0.1'), diff --git a/packages/server/test/jwt/index.spec.ts b/packages/server/test/jwt/index.spec.ts index f40aecc62..8e034191a 100644 --- a/packages/server/test/jwt/index.spec.ts +++ b/packages/server/test/jwt/index.spec.ts @@ -1,10 +1,23 @@ import path from 'path'; import request from 'supertest'; -import { HEADERS, HTTP_STATUS, HEADER_TYPE, TOKEN_BEARER, TOKEN_BASIC, API_ERROR } from '@verdaccio/dev-commons'; +import { + HEADERS, + HTTP_STATUS, + HEADER_TYPE, + TOKEN_BEARER, + TOKEN_BASIC, + API_ERROR, +} from '@verdaccio/dev-commons'; import { mockServer, generateRamdonStorage } from '@verdaccio/mock'; import { buildUserBuffer, buildToken } from '@verdaccio/utils'; -import { configExample, DOMAIN_SERVERS, addUser, getPackage, loginUserToken } from '@verdaccio/mock'; +import { + configExample, + DOMAIN_SERVERS, + addUser, + getPackage, + loginUserToken, +} from '@verdaccio/mock'; import { setup, logger } from '@verdaccio/logger'; @@ -72,7 +85,12 @@ describe('endpoint user auth JWT unit test', () => { expect(resp1.body).toBeDefined(); expect(resp1.body.name).toMatch('vue'); - const [err2, resp2] = await getPackage(request(app), FAKE_TOKEN, 'vue', HTTP_STATUS.UNAUTHORIZED); + const [err2, resp2] = await getPackage( + request(app), + FAKE_TOKEN, + 'vue', + HTTP_STATUS.UNAUTHORIZED + ); expect(err2).toBeNull(); expect(resp2.statusCode).toBe(HTTP_STATUS.UNAUTHORIZED); expect(resp2.body.error).toMatch(FORBIDDEN_VUE); @@ -106,7 +124,12 @@ describe('endpoint user auth JWT unit test', () => { }); test('should fails on try to access with corrupted token', async (done) => { - const [err2, resp2] = await getPackage(request(app), FAKE_TOKEN, 'vue', HTTP_STATUS.UNAUTHORIZED); + const [err2, resp2] = await getPackage( + request(app), + FAKE_TOKEN, + 'vue', + HTTP_STATUS.UNAUTHORIZED + ); expect(err2).toBeNull(); expect(resp2.statusCode).toBe(HTTP_STATUS.UNAUTHORIZED); expect(resp2.body.error).toMatch(FORBIDDEN_VUE); @@ -126,7 +149,13 @@ describe('endpoint user auth JWT unit test', () => { // we login when token is valid const newCredentials = { name: 'newFailsUser', password: 'BAD_PASSWORD' }; - const [err2, resp2] = await loginUserToken(request(app), newCredentials.name, newCredentials, token, HTTP_STATUS.UNAUTHORIZED); + const [err2, resp2] = await loginUserToken( + request(app), + newCredentials.name, + newCredentials, + token, + HTTP_STATUS.UNAUTHORIZED + ); expect(err2).toBeNull(); expect(resp2.statusCode).toBe(HTTP_STATUS.UNAUTHORIZED); expect(resp2.body.error).toMatch(API_ERROR.BAD_USERNAME_PASSWORD); diff --git a/packages/server/test/profile/index.spec.ts b/packages/server/test/profile/index.spec.ts index dd603d72a..fdffa02a5 100644 --- a/packages/server/test/profile/index.spec.ts +++ b/packages/server/test/profile/index.spec.ts @@ -5,7 +5,14 @@ import { mockServer } from '@verdaccio/mock'; import { API_ERROR, HTTP_STATUS, SUPPORT_ERRORS } from '@verdaccio/dev-commons'; import { setup, logger } from '@verdaccio/logger'; -import { generateRamdonStorage, getNewToken, getProfile, postProfile, configExample, DOMAIN_SERVERS } from '@verdaccio/mock'; +import { + generateRamdonStorage, + getNewToken, + getProfile, + postProfile, + configExample, + DOMAIN_SERVERS, +} from '@verdaccio/mock'; import endPointAPI from '../../src'; @@ -99,7 +106,12 @@ describe('endpoint user profile', () => { tfa: {}, }; const token = await getNewToken(request(app), credentials); - const [, resp] = await postProfile(request(app), body, token, HTTP_STATUS.SERVICE_UNAVAILABLE); + const [, resp] = await postProfile( + request(app), + body, + token, + HTTP_STATUS.SERVICE_UNAVAILABLE + ); expect(resp.error).not.toBeNull(); expect(resp.error.text).toMatch(SUPPORT_ERRORS.TFA_DISABLED); diff --git a/packages/server/test/proxy/index.spec.ts b/packages/server/test/proxy/index.spec.ts index d047c0d57..62da9fb85 100644 --- a/packages/server/test/proxy/index.spec.ts +++ b/packages/server/test/proxy/index.spec.ts @@ -4,7 +4,7 @@ import _ from 'lodash'; import { Config as AppConfig } from '@verdaccio/config'; import { Config, UpLinkConf } from '@verdaccio/types'; import { VerdaccioError } from '@verdaccio/commons-api'; -import { IProxy } from '@verdaccio/dev-types'; +import { IProxy } from '@verdaccio/proxy'; import { API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; import { mockServer, configExample, DOMAIN_SERVERS } from '@verdaccio/mock'; import { ProxyStorage } from '@verdaccio/proxy'; @@ -154,7 +154,10 @@ describe('UpStorge', () => { describe('UpStorge::isUplinkValid', () => { describe('valid use cases', () => { - const validateUpLink = (url: string, tarBallUrl = `${url}/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`) => { + const validateUpLink = ( + url: string, + tarBallUrl = `${url}/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz` + ) => { const uplinkConf = { url }; const proxy: IProxy = generateProxy(uplinkConf); @@ -184,7 +187,12 @@ describe('UpStorge', () => { // corner case https://github.com/verdaccio/verdaccio/issues/571 test('should validate tarball path against uplink case#6', () => { // same protocol, same domain, port === 443 which is also the standard for https - expect(validateUpLink('https://my.domain.test', `https://my.domain.test:443/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz`)).toBe(true); + expect( + validateUpLink( + 'https://my.domain.test', + `https://my.domain.test:443/artifactory/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz` + ) + ).toBe(true); }); test('should validate tarball path against uplink case#7', () => { @@ -229,7 +237,8 @@ describe('UpStorge', () => { test('should fails on validate tarball path against uplink case#4', () => { // same domain, same protocol, different port const url = 'https://subdomain.domain:5001'; - const tarBallUrl = 'https://subdomain.domain:4000/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz'; + const tarBallUrl = + 'https://subdomain.domain:4000/api/npm/npm/pk1-juan/-/pk1-juan-1.0.7.tgz'; const uplinkConf = { url }; const proxy: IProxy = generateProxy(uplinkConf); diff --git a/packages/server/test/storage/index.spec.ts b/packages/server/test/storage/index.spec.ts index e2a37bcf6..f54cea99f 100644 --- a/packages/server/test/storage/index.spec.ts +++ b/packages/server/test/storage/index.spec.ts @@ -3,7 +3,7 @@ import fs from 'fs'; import { Writable } from 'stream'; import { Config as AppConfig } from '@verdaccio/config'; import { Storage } from '@verdaccio/store'; -import { IStorageHandler } from '@verdaccio/dev-types'; +import { IStorageHandler } from '@verdaccio/store'; import { Config } from '@verdaccio/types'; import { API_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; @@ -139,7 +139,9 @@ describe('StorageTest', () => { reader.on('end', () => { expect(cachedSpy).toHaveBeenCalledTimes(0); expect(notcachedSpy).toHaveBeenCalledTimes(1); - expect(notcachedSpy).toHaveBeenCalledWith('http://0.0.0.0:55548/@jquery%2fjquery/-/jquery-1.5.1.tgz'); + expect(notcachedSpy).toHaveBeenCalledWith( + 'http://0.0.0.0:55548/@jquery%2fjquery/-/jquery-1.5.1.tgz' + ); res(); }); reader.on('error', (err) => { diff --git a/packages/server/test/token/index.spec.ts b/packages/server/test/token/index.spec.ts index 8fef17b99..9e6df9696 100644 --- a/packages/server/test/token/index.spec.ts +++ b/packages/server/test/token/index.spec.ts @@ -2,10 +2,23 @@ import path from 'path'; import request from 'supertest'; import _ from 'lodash'; -import { HEADERS, HTTP_STATUS, HEADER_TYPE, TOKEN_BEARER, API_ERROR, SUPPORT_ERRORS } from '@verdaccio/dev-commons'; +import { + HEADERS, + HTTP_STATUS, + HEADER_TYPE, + TOKEN_BEARER, + API_ERROR, + SUPPORT_ERRORS, +} from '@verdaccio/dev-commons'; import { buildToken } from '@verdaccio/utils'; -import { generateRamdonStorage, DOMAIN_SERVERS, mockServer, getNewToken, configExample } from '@verdaccio/mock'; +import { + generateRamdonStorage, + DOMAIN_SERVERS, + mockServer, + getNewToken, + configExample, +} from '@verdaccio/mock'; import { setup, logger } from '@verdaccio/logger'; diff --git a/packages/server/test/web/index.spec.ts b/packages/server/test/web/index.spec.ts index 3945854a7..c2597a195 100644 --- a/packages/server/test/web/index.spec.ts +++ b/packages/server/test/web/index.spec.ts @@ -3,7 +3,13 @@ import request from 'supertest'; import { HEADERS, API_ERROR, HTTP_STATUS, HEADER_TYPE, DIST_TAGS } from '@verdaccio/dev-commons'; -import { addUser, mockServer, DOMAIN_SERVERS, configExample, generateRamdonStorage } from '@verdaccio/mock'; +import { + addUser, + mockServer, + DOMAIN_SERVERS, + configExample, + generateRamdonStorage, +} from '@verdaccio/mock'; import { setup, logger } from '@verdaccio/logger'; import endPointAPI from '../../src'; @@ -58,7 +64,11 @@ describe('endpoint web unit test', () => { .send(JSON.stringify(publishMetadata)) .expect(HTTP_STATUS.CREATED); - await request(app).put('/forbidden-place').set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON).send(JSON.stringify(forbiddenPlace)).expect(HTTP_STATUS.CREATED); + await request(app) + .put('/forbidden-place') + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send(JSON.stringify(forbiddenPlace)) + .expect(HTTP_STATUS.CREATED); }); describe('Packages', () => { diff --git a/packages/server/test/web/partials/forbidden-place.js b/packages/server/test/web/partials/forbidden-place.js index ee87990dd..23ec4c1ae 100644 --- a/packages/server/test/web/partials/forbidden-place.js +++ b/packages/server/test/web/partials/forbidden-place.js @@ -30,7 +30,8 @@ const json = { _nodeVersion: '8.7.0', _npmUser: {}, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', tarball: 'http://localhost:5555/forbidden-place/-/forbidden-place-1.0.6.tgz', }, diff --git a/packages/server/test/web/partials/publish-api.js b/packages/server/test/web/partials/publish-api.js index 099fc4124..b0cb4a890 100644 --- a/packages/server/test/web/partials/publish-api.js +++ b/packages/server/test/web/partials/publish-api.js @@ -30,7 +30,8 @@ const json = { _nodeVersion: '8.7.0', _npmUser: {}, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', tarball: 'http://localhost:5555/@scope/pk1-test/-/@scope/pk1-test-1.0.6.tgz', }, diff --git a/packages/server/types/custom.d.ts b/packages/server/types/custom.d.ts index dfc4ffcdd..72cee6d7d 100644 --- a/packages/server/types/custom.d.ts +++ b/packages/server/types/custom.d.ts @@ -1,4 +1,9 @@ import { Logger, RemoteUser } from '@verdaccio/types'; +import { NextFunction, Request, Response } from 'express'; + +export type $RequestExtend = Request & { remote_user?: any; log: Logger }; +export type $ResponseExtend = Response & { cookies?: any }; +export type $NextFunctionVer = NextFunction & any; declare global { namespace Express { diff --git a/packages/store/package.json b/packages/store/package.json index d419ca3f3..3ba3d3fd4 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -39,7 +39,6 @@ }, "devDependencies": { "@verdaccio/config": "workspace:5.0.0-alpha.0", - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/mock": "workspace:5.0.0-alpha.0", "@verdaccio/types": "workspace:*" } diff --git a/packages/store/src/local-storage.ts b/packages/store/src/local-storage.ts index be6585f00..fa2aacc77 100644 --- a/packages/store/src/local-storage.ts +++ b/packages/store/src/local-storage.ts @@ -4,7 +4,14 @@ import _ from 'lodash'; import buildDebug from 'debug'; import { ErrorCode, isObject, getLatestVersion, tagVersion, validateName } from '@verdaccio/utils'; -import { API_ERROR, DIST_TAGS, HTTP_STATUS, STORAGE, SUPPORT_ERRORS, USERS } from '@verdaccio/dev-commons'; +import { + API_ERROR, + DIST_TAGS, + HTTP_STATUS, + STORAGE, + SUPPORT_ERRORS, + USERS, +} from '@verdaccio/dev-commons'; import { createTarballHash } from '@verdaccio/utils'; import { loadPlugin } from '@verdaccio/loaders'; import LocalDatabase from '@verdaccio/local-storage'; @@ -26,11 +33,12 @@ import { Author, CallbackAction, onSearchPackage, + StringValue, onEndSearchPackage, StorageUpdateCallback, } from '@verdaccio/types'; -import { IStorage, StringValue } from '@verdaccio/dev-types'; import { VerdaccioError } from '@verdaccio/commons-api'; +import { IStorage } from './storage'; import { prepareSearchPackage, @@ -69,7 +77,10 @@ class LocalStorage implements IStorage { } storage.createPackage(name, generatePackageTemplate(name), (err) => { - if (_.isNull(err) === false && (err.code === STORAGE.FILE_EXIST_ERROR || err.code === HTTP_STATUS.CONFLICT)) { + if ( + _.isNull(err) === false && + (err.code === STORAGE.FILE_EXIST_ERROR || err.code === HTTP_STATUS.CONFLICT) + ) { debug(`error on creating a package for %o with error %o`, name, err.message); return callback(ErrorCode.getConflict()); } @@ -187,7 +198,10 @@ class LocalStorage implements IStorage { debug('update dist-tags'); for (const tag in packageInfo[DIST_TAGS]) { - if (!packageLocalJson[DIST_TAGS][tag] || packageLocalJson[DIST_TAGS][tag] !== packageInfo[DIST_TAGS][tag]) { + if ( + !packageLocalJson[DIST_TAGS][tag] || + packageLocalJson[DIST_TAGS][tag] !== packageInfo[DIST_TAGS][tag] + ) { change = true; packageLocalJson[DIST_TAGS][tag] = packageInfo[DIST_TAGS][tag]; } @@ -232,7 +246,13 @@ class LocalStorage implements IStorage { * @param {*} tag * @param {*} callback */ - public addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: CallbackAction): void { + public addVersion( + name: string, + version: string, + metadata: Version, + tag: StringValue, + callback: CallbackAction + ): void { debug(`add version package for`, name); this._updatePackage( name, @@ -254,7 +274,10 @@ class LocalStorage implements IStorage { const tarball = metadata.dist.tarball.replace(/.*\//, ''); if (isObject(data._attachments[tarball])) { - if (_.isNil(data._attachments[tarball].shasum) === false && _.isNil(metadata.dist.shasum) === false) { + if ( + _.isNil(data._attachments[tarball].shasum) === false && + _.isNil(metadata.dist.shasum) === false + ) { if (data._attachments[tarball].shasum != metadata.dist.shasum) { const errorMessage = `shasum error, ${data._attachments[tarball].shasum} != ${metadata.dist.shasum}`; return cb(ErrorCode.getBadRequest(errorMessage)); @@ -352,7 +375,12 @@ class LocalStorage implements IStorage { * @param {*} callback * @return {Function} */ - public changePackage(name: string, incomingPkg: Package, revision: string | void, callback: Callback): void { + public changePackage( + name: string, + incomingPkg: Package, + revision: string | void, + callback: Callback + ): void { debug(`change package tags for %o revision`, name); if (!isObject(incomingPkg.versions) || !isObject(incomingPkg[DIST_TAGS])) { debug(`change package bad data for %o`, name); @@ -381,10 +409,16 @@ class LocalStorage implements IStorage { const incomingDeprecated = incomingVersion.deprecated; if (incomingDeprecated != localData.versions[version].deprecated) { if (!incomingDeprecated) { - this.logger.info({ name: name, version: version }, 'undeprecating @{name}@@{version}'); + this.logger.info( + { name: name, version: version }, + 'undeprecating @{name}@@{version}' + ); delete localData.versions[version].deprecated; } else { - this.logger.info({ name: name, version: version }, 'deprecating @{name}@@{version}'); + this.logger.info( + { name: name, version: version }, + 'deprecating @{name}@@{version}' + ); localData.versions[version].deprecated = incomingDeprecated; } localData.time!.modified = new Date().toISOString(); @@ -411,7 +445,12 @@ class LocalStorage implements IStorage { * @param {*} revision * @param {*} callback */ - public removeTarball(name: string, filename: string, revision: string, callback: CallbackAction): void { + public removeTarball( + name: string, + filename: string, + revision: string, + callback: CallbackAction + ): void { assert(validateName(filename)); this._updatePackage( @@ -765,14 +804,24 @@ class LocalStorage implements IStorage { * @param {*} callback callback that gets invoked after it's all updated * @return {Function} */ - private _updatePackage(name: string, updateHandler: StorageUpdateCallback, callback: CallbackAction): void { + private _updatePackage( + name: string, + updateHandler: StorageUpdateCallback, + callback: CallbackAction + ): void { const storage: IPackageStorage = this._getLocalStorage(name); if (!storage) { return callback(ErrorCode.getNotFound()); } - storage.updatePackage(name, updateHandler, this._writePackage.bind(this), normalizePackage, callback); + storage.updatePackage( + name, + updateHandler, + this._writePackage.bind(this), + normalizePackage, + callback + ); } /** @@ -882,7 +931,9 @@ class LocalStorage implements IStorage { public saveToken(token: Token): Promise { if (_.isFunction(this.storagePlugin.saveToken) === false) { - return Promise.reject(ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE)); + return Promise.reject( + ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE) + ); } return this.storagePlugin.saveToken(token); @@ -890,7 +941,9 @@ class LocalStorage implements IStorage { public deleteToken(user: string, tokenKey: string): Promise { if (_.isFunction(this.storagePlugin.deleteToken) === false) { - return Promise.reject(ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE)); + return Promise.reject( + ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE) + ); } return this.storagePlugin.deleteToken(user, tokenKey); @@ -898,7 +951,9 @@ class LocalStorage implements IStorage { public readTokens(filter: TokenFilter): Promise { if (_.isFunction(this.storagePlugin.readTokens) === false) { - return Promise.reject(ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE)); + return Promise.reject( + ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.PLUGIN_MISSING_INTERFACE) + ); } return this.storagePlugin.readTokens(filter); diff --git a/packages/store/src/search.ts b/packages/store/src/search.ts index 3cb99c6db..677a211e7 100644 --- a/packages/store/src/search.ts +++ b/packages/store/src/search.ts @@ -2,7 +2,18 @@ import lunrMutable from 'lunr-mutable-indexes'; import { Version } from '@verdaccio/types'; -import { IStorageHandler, IWebSearch, IStorage } from '@verdaccio/dev-types'; +import { IStorageHandler, IStorage } from './storage'; + +export interface IWebSearch { + index: lunrMutable.index; + storage: IStorageHandler; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + query(query: string): any; + add(pkg: Version): void; + remove(name: string): void; + reindex(): void; + configureStorage(storage: IStorageHandler): void; +} /** * Handle the search Indexer. */ diff --git a/packages/store/src/storage-utils.ts b/packages/store/src/storage-utils.ts index 276f4ab77..94493a3e6 100644 --- a/packages/store/src/storage-utils.ts +++ b/packages/store/src/storage-utils.ts @@ -1,11 +1,18 @@ import _ from 'lodash'; -import { ErrorCode, isObject, normalizeDistTags, semverSort, generateRandomHexString, isNil } from '@verdaccio/utils'; +import { + ErrorCode, + isObject, + normalizeDistTags, + semverSort, + generateRandomHexString, + isNil, +} from '@verdaccio/utils'; import { Package, Version, Author } from '@verdaccio/types'; -import { IStorage } from '@verdaccio/dev-types'; import { API_ERROR, HTTP_STATUS, DIST_TAGS, USERS, STORAGE } from '@verdaccio/dev-commons'; import { SearchInstance } from './search'; +import { IStorage } from './storage'; export function generatePackageTemplate(name: string): Package { return { @@ -107,7 +114,16 @@ export function normalizeContributors(contributors: Author[]): Author[] { return contributors; } -export const WHITELIST = ['_rev', 'name', 'versions', 'dist-tags', 'readme', 'time', '_id', 'users']; +export const WHITELIST = [ + '_rev', + 'name', + 'versions', + 'dist-tags', + 'readme', + 'time', + '_id', + 'users', +]; export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Package { const propertyToKeep = [...WHITELIST]; @@ -157,7 +173,11 @@ export function publishPackage(name: string, metadata: any, localStorage: IStora }); } -export function checkPackageRemote(name: string, isAllowPublishOffline: boolean, syncMetadata: Function): Promise { +export function checkPackageRemote( + name: string, + isAllowPublishOffline: boolean, + syncMetadata: Function +): Promise { return new Promise((resolve, reject): void => { syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => { // something weird @@ -200,7 +220,8 @@ export function mergeUplinkTimeIntoLocal(localMetadata: Package, remoteMetadata: export function prepareSearchPackage(data: Package, time: unknown): any { const listVersions: string[] = Object.keys(data.versions); const versions: string[] = semverSort(listVersions); - const latest: string | undefined = data[DIST_TAGS] && data[DIST_TAGS].latest ? data[DIST_TAGS].latest : versions.pop(); + const latest: string | undefined = + data[DIST_TAGS] && data[DIST_TAGS].latest ? data[DIST_TAGS].latest : versions.pop(); if (latest && data.versions[latest]) { const version: Version = data.versions[latest]; diff --git a/packages/store/src/storage.ts b/packages/store/src/storage.ts index 7d587b2b6..37986dde8 100644 --- a/packages/store/src/storage.ts +++ b/packages/store/src/storage.ts @@ -2,27 +2,94 @@ import assert from 'assert'; import Stream from 'stream'; import async, { AsyncResultArrayCallback } from 'async'; import _ from 'lodash'; +import { Request } from 'express'; import buildDebug from 'debug'; import { ProxyStorage } from '@verdaccio/proxy'; import { API_ERROR, HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons'; import { ReadTarball } from '@verdaccio/streams'; -import { ErrorCode, normalizeDistTags, validateMetadata, isObject, hasProxyTo } from '@verdaccio/utils'; -import { setupUpLinks, updateVersionsHiddenUpLink } from '@verdaccio/proxy'; -import { IReadTarball, IUploadTarball, Versions, Package, Config, MergeTags, Version, DistFile, Callback, Logger } from '@verdaccio/types'; -import { IStorage, IProxy, IStorageHandler, ProxyList, StringValue, IGetPackageOptions, ISyncUplinks, IPluginFilters } from '@verdaccio/dev-types'; -import { GenericBody, TokenFilter, Token } from '@verdaccio/types'; +import { + ErrorCode, + normalizeDistTags, + validateMetadata, + isObject, + hasProxyTo, +} from '@verdaccio/utils'; +import { setupUpLinks, updateVersionsHiddenUpLink, ProxyList, IProxy } from '@verdaccio/proxy'; +import { + IReadTarball, + IUploadTarball, + Versions, + Package, + Config, + MergeTags, + Version, + DistFile, + StringValue, + IPluginStorageFilter, + IBasicStorage, + IPluginStorage, + Callback, + Logger, + GenericBody, + TokenFilter, + Token, + IStorageManager, + ITokenActions, +} from '@verdaccio/types'; import { logger } from '@verdaccio/logger'; import { VerdaccioError } from '@verdaccio/commons-api'; import { SearchInstance } from './search'; import { LocalStorage } from './local-storage'; import { mergeVersions } from './metadata-utils'; -import { checkPackageLocal, publishPackage, checkPackageRemote, cleanUpLinksRef, mergeUplinkTimeIntoLocal, generatePackageTemplate } from './storage-utils'; +import { + checkPackageLocal, + publishPackage, + checkPackageRemote, + cleanUpLinksRef, + mergeUplinkTimeIntoLocal, + generatePackageTemplate, +} from './storage-utils'; const debug = buildDebug('verdaccio:storage'); -class Storage implements IStorageHandler { +export interface IGetPackageOptions { + callback: Callback; + name: string; + keepUpLinkData: boolean; + uplinksLook: boolean; + req: any; +} + +export interface IStorage extends IBasicStorage, ITokenActions { + config: Config; + storagePlugin: IPluginStorage; + logger: Logger; +} + +export interface ISyncUplinks { + uplinksLook?: boolean; + etag?: string; + req?: Request; +} + +export type IPluginFilters = IPluginStorageFilter[]; + +export interface IStorageHandler extends IStorageManager, ITokenActions { + config: Config; + localStorage: IStorage | null; + filters: IPluginFilters; + uplinks: ProxyList; + init(config: Config, filters: IPluginFilters): Promise; + saveToken(token: Token): Promise; + deleteToken(user: string, tokenKey: string): Promise; + readTokens(filter: TokenFilter): Promise; + _syncUplinksMetadata(name: string, packageInfo: Package, options: any, callback: Callback): void; + _updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void; +} + +class Storage { public localStorage: IStorage; public config: Config; public logger: Logger; @@ -58,7 +125,11 @@ class Storage implements IStorageHandler { debug('add package for %o', name); await checkPackageLocal(name, this.localStorage); debug('look up remote for %o', name); - await checkPackageRemote(name, this._isAllowPublishOffline(), this._syncUplinksMetadata.bind(this)); + await checkPackageRemote( + name, + this._isAllowPublishOffline(), + this._syncUplinksMetadata.bind(this) + ); debug('publishing a package for %o', name); await publishPackage(name, metadata, this.localStorage as IStorage); callback(); @@ -69,7 +140,11 @@ class Storage implements IStorageHandler { } private _isAllowPublishOffline(): boolean { - return typeof this.config.publish !== 'undefined' && _.isBoolean(this.config.publish.allow_offline) && this.config.publish.allow_offline; + return ( + typeof this.config.publish !== 'undefined' && + _.isBoolean(this.config.publish.allow_offline) && + this.config.publish.allow_offline + ); } public readTokens(filter: TokenFilter): Promise { @@ -88,7 +163,13 @@ class Storage implements IStorageHandler { * Add a new version of package {name} to a system Used storages: local (write) */ - public addVersion(name: string, version: string, metadata: Version, tag: StringValue, callback: Callback): void { + public addVersion( + name: string, + version: string, + metadata: Version, + tag: StringValue, + callback: Callback + ): void { debug('add the version %o for package %o', version, name); this.localStorage.addVersion(name, version, metadata, tag, callback); } @@ -107,7 +188,12 @@ class Storage implements IStorageHandler { Function changes a package info from local storage and all uplinks with write access./ Used storages: local (write) */ - public changePackage(name: string, metadata: Package, revision: string, callback: Callback): void { + public changePackage( + name: string, + metadata: Package, + revision: string, + callback: Callback + ): void { debug('change existing package for package %o revision %o', name, revision); this.localStorage.changePackage(name, metadata, revision, callback); } @@ -266,7 +352,10 @@ class Storage implements IStorageHandler { }); savestream.on('error', function (err): void { - self.logger.warn({ err: err, fileName: file }, 'error saving file @{fileName}: @{err?.message}\n@{err.stack}'); + self.logger.warn( + { err: err, fileName: file }, + 'error saving file @{fileName}: @{err?.message}\n@{err.stack}' + ); if (savestream) { savestream.abort(); } @@ -303,24 +392,25 @@ class Storage implements IStorageHandler { } debug('sync uplinks for %o', name); - this._syncUplinksMetadata(name, data, { req: options.req, uplinksLook: options.uplinksLook }, function getPackageSynUpLinksCallback( - err, - result: Package, - uplinkErrors - ): void { - if (err) { - debug('error on sync package for %o with error %o', name, err?.message); - return options.callback(err); + this._syncUplinksMetadata( + name, + data, + { req: options.req, uplinksLook: options.uplinksLook }, + function getPackageSynUpLinksCallback(err, result: Package, uplinkErrors): void { + if (err) { + debug('error on sync package for %o with error %o', name, err?.message); + return options.callback(err); + } + + normalizeDistTags(cleanUpLinksRef(options.keepUpLinkData, result)); + + // npm can throw if this field doesn't exist + result._attachments = {}; + + debug('sync uplinks errors %o', uplinkErrors); + options.callback(null, result, uplinkErrors); } - - normalizeDistTags(cleanUpLinksRef(options.keepUpLinkData, result)); - - // npm can throw if this field doesn't exist - result._attachments = {}; - - debug('sync uplinks errors %o', uplinkErrors); - options.callback(null, result, uplinkErrors); - }); + ); }); } @@ -401,7 +491,10 @@ class Storage implements IStorageHandler { const packages: Version[] = []; const getPackage = function (itemPkg): void { - self.localStorage.getPackageMetadata(locals[itemPkg], function (err, pkgMetadata: Package): void { + self.localStorage.getPackageMetadata(locals[itemPkg], function ( + err, + pkgMetadata: Package + ): void { if (_.isNil(err)) { const latest = pkgMetadata[DIST_TAGS].latest; if (latest && pkgMetadata.versions[latest]) { @@ -417,7 +510,10 @@ class Storage implements IStorageHandler { packages.push(version); } else { - self.logger.warn({ package: locals[itemPkg] }, 'package @{package} does not have a "latest" tag?'); + self.logger.warn( + { package: locals[itemPkg] }, + 'package @{package} does not have a "latest" tag?' + ); } } @@ -442,7 +538,12 @@ class Storage implements IStorageHandler { if package is available locally, it MUST be provided in pkginfo returns callback(err, result, uplink_errors) */ - public _syncUplinksMetadata(name: string, packageInfo: Package, options: ISyncUplinks, callback: Callback): void { + public _syncUplinksMetadata( + name: string, + packageInfo: Package, + options: ISyncUplinks, + callback: Callback + ): void { let found = true; const self = this; const upLinks: IProxy[] = []; diff --git a/packages/store/test/local-storage.spec.ts b/packages/store/test/local-storage.spec.ts index 8f268d5be..bc936e2ba 100644 --- a/packages/store/test/local-storage.spec.ts +++ b/packages/store/test/local-storage.spec.ts @@ -5,7 +5,7 @@ import { Config as AppConfig } from '@verdaccio/config'; // @ts-ignore import { logger, setup } from '@verdaccio/logger'; import { configExample, generateNewVersion } from '@verdaccio/mock'; -import { IStorage } from '@verdaccio/dev-types'; +import { IStorage } from '../src/storage'; const readMetadata = (fileName = 'metadata') => readFile(`../fixtures/${fileName}`).toString(); import { Config, MergeTags, Package } from '@verdaccio/types'; @@ -44,9 +44,15 @@ describe('LocalStorage', () => { const addNewVersion = (pkgName: string, version: string) => { return new Promise((resolve) => { - storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', (err, data) => { - resolve(data); - }); + storage.addVersion( + pkgName, + version, + generateNewVersion(pkgName, version), + '', + (err, data) => { + resolve(data); + } + ); }); }; const addTarballToStore = (pkgName: string, tarballName) => { @@ -203,11 +209,17 @@ describe('LocalStorage', () => { await addTarballToStore(pkgName, `${pkgName}-9.0.0.tgz`); await addTarballToStore(pkgName, tarballName); - storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), '', (err, data) => { - expect(err).toBeNull(); - expect(data).toBeUndefined(); - done(); - }); + storage.addVersion( + pkgName, + version, + generateNewVersion(pkgName, version), + '', + (err, data) => { + expect(err).toBeNull(); + expect(data).toBeUndefined(); + done(); + } + ); }); test('should fails on add a duplicated version without tag', async (done) => { @@ -231,12 +243,18 @@ describe('LocalStorage', () => { const tarballName = `${pkgName}-${version}.tgz`; await addTarballToStore(pkgName, tarballName); - storage.addVersion(pkgName, version, generateNewVersion(pkgName, version, 'fake'), '', (err) => { - expect(err).not.toBeNull(); - expect(err.statusCode).toEqual(HTTP_STATUS.BAD_REQUEST); - expect(err.message).toMatch(/shasum error/); - done(); - }); + storage.addVersion( + pkgName, + version, + generateNewVersion(pkgName, version, 'fake'), + '', + (err) => { + expect(err).not.toBeNull(); + expect(err.statusCode).toEqual(HTTP_STATUS.BAD_REQUEST); + expect(err.message).toMatch(/shasum error/); + done(); + } + ); }); test('should add new second version without tag', async (done) => { @@ -246,11 +264,17 @@ describe('LocalStorage', () => { await addNewVersion(pkgName, '1.0.1'); await addNewVersion(pkgName, '1.0.3'); - storage.addVersion(pkgName, version, generateNewVersion(pkgName, version), 'beta', (err, data) => { - expect(err).toBeNull(); - expect(data).toBeUndefined(); - done(); - }); + storage.addVersion( + pkgName, + version, + generateNewVersion(pkgName, version), + 'beta', + (err, data) => { + expect(err).toBeNull(); + expect(data).toBeUndefined(); + done(); + } + ); }); }); diff --git a/packages/store/test/merge.dist.tags.spec.ts b/packages/store/test/merge.dist.tags.spec.ts index 1e5989d90..f9d9a1771 100644 --- a/packages/store/test/merge.dist.tags.spec.ts +++ b/packages/store/test/merge.dist.tags.spec.ts @@ -58,6 +58,11 @@ describe('Storage._merge_versions versions', () => { }); test('semverSort', () => { - assert.deepEqual(semverSort(['1.2.3', '1.2', '1.2.3a', '1.2.3c', '1.2.3-b']), ['1.2.3a', '1.2.3-b', '1.2.3c', '1.2.3']); + assert.deepEqual(semverSort(['1.2.3', '1.2', '1.2.3a', '1.2.3c', '1.2.3-b']), [ + '1.2.3a', + '1.2.3-b', + '1.2.3c', + '1.2.3', + ]); }); }); diff --git a/packages/store/test/storage-utils.spec.ts b/packages/store/test/storage-utils.spec.ts index d7b5eff30..3b5113f7f 100644 --- a/packages/store/test/storage-utils.spec.ts +++ b/packages/store/test/storage-utils.spec.ts @@ -88,7 +88,12 @@ describe('Storage Utils', () => { }; const mergedPkg = mergeUplinkTimeIntoLocal(pkg1, pkg2); - expect(Object.keys(mergedPkg)).toEqual(['modified', 'created', ...Object.keys(vGroup1), ...Object.keys(vGroup2)]); + expect(Object.keys(mergedPkg)).toEqual([ + 'modified', + 'created', + ...Object.keys(vGroup1), + ...Object.keys(vGroup2), + ]); }); test('mergeTime remote empty', () => { diff --git a/packages/types/index.ts b/packages/types/index.ts index fc3046e6c..db12a0bac 100644 --- a/packages/types/index.ts +++ b/packages/types/index.ts @@ -1,76 +1,18 @@ import { - IBasicAuth, IBasicStorage, - IStorageManager, - UpLinkConf, Callback, - Versions, - Version, RemoteUser, Config, Logger, - JWTSignOptions, - PackageAccess, IPluginStorage, - StringValue as verdaccio$StringValue, - IReadTarball, Package, - IPluginStorageFilter, - Author, - AuthPluginPackage, - Token, ITokenActions, - TokenFilter, } from '@verdaccio/types'; -import lunrMutable from 'lunr-mutable-indexes'; -import { NextFunction, Request, Response } from 'express'; - -export type StringValue = verdaccio$StringValue; - -export interface StartUpConfig { - storage: string; - plugins?: string; - self_path: string; -} - -// legacy should be removed in long term - -export interface LegacyPackageList { - [key: string]: PackageAccessAddOn; -} - -export type PackageAccessAddOn = PackageAccess & { - // FIXME: should be published on @verdaccio/types - unpublish?: string[]; -}; - -export type MatchedPackage = PackageAccess | void; export type JWTPayload = RemoteUser & { password?: string; }; -export interface AESPayload { - user: string; - password: string; -} - -export interface AuthTokenHeader { - scheme: string; - token: string; -} - -export type BasicPayload = AESPayload | void; -export type AuthMiddlewarePayload = RemoteUser | BasicPayload; - -export interface ProxyList { - [key: string]: IProxy; -} - -export interface CookieSessionToken { - expires: Date; -} - export interface Utils { ErrorCode: any; getLatestVersion: Callback; @@ -92,105 +34,15 @@ export interface Profile { fullname: string; } -export type $RequestExtend = Request & { remote_user?: any; log: Logger }; -export type $ResponseExtend = Response & { cookies?: any }; -export type $NextFunctionVer = NextFunction & any; -export type $SidebarPackage = Package & { latest: any }; - -export interface IAuthWebUI { - jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise; - aesEncrypt(buf: Buffer): Buffer; -} - -interface IAuthMiddleware { - apiJWTmiddleware(): $NextFunctionVer; - webUIJWTmiddleware(): $NextFunctionVer; -} - -export interface IAuth extends IBasicAuth, IAuthMiddleware, IAuthWebUI { - config: Config; - logger: Logger; - secret: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - plugins: any[]; - allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void; -} - -export interface IWebSearch { - index: lunrMutable.index; - storage: IStorageHandler; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - query(query: string): any; - add(pkg: Version): void; - remove(name: string): void; - reindex(): void; - configureStorage(storage: IStorageHandler): void; -} - -// FIXME: This prop should be on @verdaccio/types -export type UpLinkConfLocal = UpLinkConf & { - no_proxy?: string; -}; - -export interface IProxy { - config: UpLinkConfLocal; - failed_requests: number; - userAgent: string; - ca?: string | void; - logger: Logger; - server_id: string; - url: any; - maxage: number; - timeout: number; - max_fails: number; - fail_timeout: number; - upname: string; - fetchTarball(url: string): IReadTarball; - isUplinkValid(url: string): boolean; - search(options: any); - getRemoteMetadata(name: string, options: any, callback: Callback): void; -} - export interface IStorage extends IBasicStorage, ITokenActions { config: Config; storagePlugin: IPluginStorage; logger: Logger; } -export interface IGetPackageOptions { - callback: Callback; - name: string; - keepUpLinkData: boolean; - uplinksLook: boolean; - req: any; -} - -export interface ISyncUplinks { - uplinksLook?: boolean; - etag?: string; - req?: Request; -} - -export type IPluginFilters = IPluginStorageFilter[]; - -export interface IStorageHandler extends IStorageManager, ITokenActions { - config: Config; - localStorage: IStorage | null; - filters: IPluginFilters; - uplinks: ProxyList; - init(config: Config, filters: IPluginFilters): Promise; - saveToken(token: Token): Promise; - deleteToken(user: string, tokenKey: string): Promise; - readTokens(filter: TokenFilter): Promise; - _syncUplinksMetadata(name: string, packageInfo: Package, options: any, callback: Callback): void; - _updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void; -} - /** * @property { string | number | Styles } [ruleOrSelector] */ export interface Styles { [ruleOrSelector: string]: string | number | Styles; } - -export type AuthorAvatar = Author & { avatar?: string }; diff --git a/packages/types/package.json b/packages/types/package.json index 37a4f112d..7e3eb8a71 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -4,6 +4,7 @@ "private": true, "description": "types for verdaccio local dev", "main": "./index.ts", + "types": "index.ts", "author": { "name": "Juan Picado", "email": "juanpicado19@gmail.com" @@ -19,6 +20,7 @@ "license": "MIT", "scripts": { "clean": "rimraf ./build", + "build": "tsc --emitDeclarationOnly -p tsconfig.build.json", "test": "echo \"Error: no test specified\" && exit 0" } } diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts new file mode 100644 index 000000000..fc3046e6c --- /dev/null +++ b/packages/types/src/index.ts @@ -0,0 +1,196 @@ +import { + IBasicAuth, + IBasicStorage, + IStorageManager, + UpLinkConf, + Callback, + Versions, + Version, + RemoteUser, + Config, + Logger, + JWTSignOptions, + PackageAccess, + IPluginStorage, + StringValue as verdaccio$StringValue, + IReadTarball, + Package, + IPluginStorageFilter, + Author, + AuthPluginPackage, + Token, + ITokenActions, + TokenFilter, +} from '@verdaccio/types'; +import lunrMutable from 'lunr-mutable-indexes'; +import { NextFunction, Request, Response } from 'express'; + +export type StringValue = verdaccio$StringValue; + +export interface StartUpConfig { + storage: string; + plugins?: string; + self_path: string; +} + +// legacy should be removed in long term + +export interface LegacyPackageList { + [key: string]: PackageAccessAddOn; +} + +export type PackageAccessAddOn = PackageAccess & { + // FIXME: should be published on @verdaccio/types + unpublish?: string[]; +}; + +export type MatchedPackage = PackageAccess | void; + +export type JWTPayload = RemoteUser & { + password?: string; +}; + +export interface AESPayload { + user: string; + password: string; +} + +export interface AuthTokenHeader { + scheme: string; + token: string; +} + +export type BasicPayload = AESPayload | void; +export type AuthMiddlewarePayload = RemoteUser | BasicPayload; + +export interface ProxyList { + [key: string]: IProxy; +} + +export interface CookieSessionToken { + expires: Date; +} + +export interface Utils { + ErrorCode: any; + getLatestVersion: Callback; + isObject: (value: any) => boolean; + validate_name: (value: any) => boolean; + tag_version: (value: any, version: string, tag: string) => void; + normalizeDistTags: (pkg: Package) => void; + semverSort: (keys: string[]) => string[]; +} + +export interface Profile { + tfa: boolean; + name: string; + email: string; + email_verified: string; + created: string; + updated: string; + cidr_whitelist: any; + fullname: string; +} + +export type $RequestExtend = Request & { remote_user?: any; log: Logger }; +export type $ResponseExtend = Response & { cookies?: any }; +export type $NextFunctionVer = NextFunction & any; +export type $SidebarPackage = Package & { latest: any }; + +export interface IAuthWebUI { + jwtEncrypt(user: RemoteUser, signOptions: JWTSignOptions): Promise; + aesEncrypt(buf: Buffer): Buffer; +} + +interface IAuthMiddleware { + apiJWTmiddleware(): $NextFunctionVer; + webUIJWTmiddleware(): $NextFunctionVer; +} + +export interface IAuth extends IBasicAuth, IAuthMiddleware, IAuthWebUI { + config: Config; + logger: Logger; + secret: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + plugins: any[]; + allow_unpublish(pkg: AuthPluginPackage, user: RemoteUser, callback: Callback): void; +} + +export interface IWebSearch { + index: lunrMutable.index; + storage: IStorageHandler; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + query(query: string): any; + add(pkg: Version): void; + remove(name: string): void; + reindex(): void; + configureStorage(storage: IStorageHandler): void; +} + +// FIXME: This prop should be on @verdaccio/types +export type UpLinkConfLocal = UpLinkConf & { + no_proxy?: string; +}; + +export interface IProxy { + config: UpLinkConfLocal; + failed_requests: number; + userAgent: string; + ca?: string | void; + logger: Logger; + server_id: string; + url: any; + maxage: number; + timeout: number; + max_fails: number; + fail_timeout: number; + upname: string; + fetchTarball(url: string): IReadTarball; + isUplinkValid(url: string): boolean; + search(options: any); + getRemoteMetadata(name: string, options: any, callback: Callback): void; +} + +export interface IStorage extends IBasicStorage, ITokenActions { + config: Config; + storagePlugin: IPluginStorage; + logger: Logger; +} + +export interface IGetPackageOptions { + callback: Callback; + name: string; + keepUpLinkData: boolean; + uplinksLook: boolean; + req: any; +} + +export interface ISyncUplinks { + uplinksLook?: boolean; + etag?: string; + req?: Request; +} + +export type IPluginFilters = IPluginStorageFilter[]; + +export interface IStorageHandler extends IStorageManager, ITokenActions { + config: Config; + localStorage: IStorage | null; + filters: IPluginFilters; + uplinks: ProxyList; + init(config: Config, filters: IPluginFilters): Promise; + saveToken(token: Token): Promise; + deleteToken(user: string, tokenKey: string): Promise; + readTokens(filter: TokenFilter): Promise; + _syncUplinksMetadata(name: string, packageInfo: Package, options: any, callback: Callback): void; + _updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void; +} + +/** + * @property { string | number | Styles } [ruleOrSelector] + */ +export interface Styles { + [ruleOrSelector: string]: string | number | Styles; +} + +export type AuthorAvatar = Author & { avatar?: string }; diff --git a/packages/types/tsconfig.build.json b/packages/types/tsconfig.build.json new file mode 100644 index 000000000..78daca76d --- /dev/null +++ b/packages/types/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./build" + }, + "include": ["src/**/*"] +} diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json index 41716a7dd..9536a0f41 100644 --- a/packages/types/tsconfig.json +++ b/packages/types/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "../../tsconfig" + "extends": "../../tsconfig.base.json" } diff --git a/packages/utils/package.json b/packages/utils/package.json index b9bf23596..e309ca70e 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -25,7 +25,6 @@ }, "devDependencies": { "@types/minimatch": "3.0.3", - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/logger": "workspace:5.0.0-alpha.0", "lodash": "^4.17.20" }, diff --git a/packages/utils/src/auth-utils.ts b/packages/utils/src/auth-utils.ts index c6e40b721..2a45b0248 100644 --- a/packages/utils/src/auth-utils.ts +++ b/packages/utils/src/auth-utils.ts @@ -1,20 +1,47 @@ import _ from 'lodash'; -import { API_ERROR, ROLES, TIME_EXPIRATION_7D, DEFAULT_MIN_LIMIT_PASSWORD } from '@verdaccio/dev-commons'; -import { CookieSessionToken } from '@verdaccio/dev-types'; -import { RemoteUser, AllowAccess, PackageAccess, Callback, Config, Security, APITokenOptions, JWTOptions, IPluginAuth } from '@verdaccio/types'; +import { + API_ERROR, + ROLES, + TIME_EXPIRATION_7D, + DEFAULT_MIN_LIMIT_PASSWORD, +} from '@verdaccio/dev-commons'; +import { + RemoteUser, + AllowAccess, + PackageAccess, + Callback, + Config, + Security, + APITokenOptions, + JWTOptions, + IPluginAuth, +} from '@verdaccio/types'; import { VerdaccioError } from '@verdaccio/commons-api'; import { ErrorCode } from './utils'; -export function validatePassword(password: string, minLength: number = DEFAULT_MIN_LIMIT_PASSWORD): boolean { +export interface CookieSessionToken { + expires: Date; +} + +export function validatePassword( + password: string, + minLength: number = DEFAULT_MIN_LIMIT_PASSWORD +): boolean { return typeof password === 'string' && password.length >= minLength; } /** * All logged users will have by default the group $all and $authenticate */ -export const defaultLoggedUserRoles = [ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL]; +export const defaultLoggedUserRoles = [ + ROLES.$ALL, + ROLES.$AUTH, + ROLES.DEPRECATED_ALL, + ROLES.DEPRECATED_AUTH, + ROLES.ALL, +]; /** * */ @@ -54,8 +81,15 @@ export function createAnonymousRemoteUser(): RemoteUser { } export type AllowActionCallbackResponse = boolean | undefined; -export type AllowActionCallback = (error: VerdaccioError | null, allowed?: AllowActionCallbackResponse) => void; -export type AllowAction = (user: RemoteUser, pkg: AuthPackageAllow, callback: AllowActionCallback) => void; +export type AllowActionCallback = ( + error: VerdaccioError | null, + allowed?: AllowActionCallbackResponse +) => void; +export type AllowAction = ( + user: RemoteUser, + pkg: AuthPackageAllow, + callback: AllowActionCallback +) => void; export interface AuthPackageAllow extends PackageAccess, AllowAccess { // TODO: this should be on @verdaccio/types unpublish: boolean | string[]; @@ -64,7 +98,11 @@ export interface AuthPackageAllow extends PackageAccess, AllowAccess { export type ActionsAllowed = 'publish' | 'unpublish' | 'access'; export function allow_action(action: ActionsAllowed, logger): AllowAction { - return function allowActionCallback(user: RemoteUser, pkg: AuthPackageAllow, callback: AllowActionCallback): void { + return function allowActionCallback( + user: RemoteUser, + pkg: AuthPackageAllow, + callback: AllowActionCallback + ): void { logger.trace({ remote: user.name }, `[auth/allow_action]: user: @{user.name}`); const { name, groups } = user; const groupAccess = pkg[action] as string[]; @@ -80,9 +118,13 @@ export function allow_action(action: ActionsAllowed, logger): AllowAction { } if (name) { - callback(ErrorCode.getForbidden(`user ${name} is not allowed to ${action} package ${pkg.name}`)); + callback( + ErrorCode.getForbidden(`user ${name} is not allowed to ${action} package ${pkg.name}`) + ); } else { - callback(ErrorCode.getUnauthorized(`authorization required to ${action} package ${pkg.name}`)); + callback( + ErrorCode.getUnauthorized(`authorization required to ${action} package ${pkg.name}`) + ); } }; } @@ -96,13 +138,19 @@ export function handleSpecialUnpublish(logger): any { // verify whether the unpublish prop has been defined const isUnpublishMissing: boolean = _.isNil(pkg[action]); const hasGroups: boolean = isUnpublishMissing ? false : (pkg[action] as string[]).length > 0; - logger.trace({ user: user.name, name: pkg.name, hasGroups }, `fallback unpublish for @{name} has groups: @{hasGroups} for @{user}`); + logger.trace( + { user: user.name, name: pkg.name, hasGroups }, + `fallback unpublish for @{name} has groups: @{hasGroups} for @{user}` + ); if (isUnpublishMissing || hasGroups === false) { return callback(null, undefined); } - logger.trace({ user: user.name, name: pkg.name, action, hasGroups }, `allow_action for @{action} for @{name} has groups: @{hasGroups} for @{user}`); + logger.trace( + { user: user.name, name: pkg.name, action, hasGroups }, + `allow_action for @{action} for @{name} has groups: @{hasGroups} for @{user}` + ); return allow_action(action, logger)(user, pkg, callback); }; } diff --git a/packages/utils/src/config-utils.ts b/packages/utils/src/config-utils.ts index 37605003d..e66dd45f8 100644 --- a/packages/utils/src/config-utils.ts +++ b/packages/utils/src/config-utils.ts @@ -2,10 +2,20 @@ import assert from 'assert'; import _ from 'lodash'; import minimatch from 'minimatch'; -import { PackageList, UpLinksConfList } from '@verdaccio/types'; -import { MatchedPackage, LegacyPackageList } from '@verdaccio/dev-types'; +import { PackageList, UpLinksConfList, PackageAccess } from '@verdaccio/types'; import { ErrorCode } from './utils'; +export type PackageAccessAddOn = PackageAccess & { + // FIXME: should be published on @verdaccio/types + unpublish?: string[]; +}; + +export interface LegacyPackageList { + [key: string]: PackageAccessAddOn; +} + +export type MatchedPackage = PackageAccess | void; + const BLACKLIST = { all: true, anonymous: true, @@ -32,13 +42,18 @@ export function normalizeUserList(groupsList: any): any { } else if (Array.isArray(groupsList)) { result.push(groupsList); } else { - throw ErrorCode.getInternalError('CONFIG: bad package acl (array or string expected): ' + JSON.stringify(groupsList)); + throw ErrorCode.getInternalError( + 'CONFIG: bad package acl (array or string expected): ' + JSON.stringify(groupsList) + ); } return _.flatten(result); } -export function uplinkSanityCheck(uplinks: UpLinksConfList, users: any = BLACKLIST): UpLinksConfList { +export function uplinkSanityCheck( + uplinks: UpLinksConfList, + users: any = BLACKLIST +): UpLinksConfList { const newUplinks = _.clone(uplinks); let newUsers = _.clone(users); @@ -55,7 +70,14 @@ export function uplinkSanityCheck(uplinks: UpLinksConfList, users: any = BLACKLI } export function sanityCheckNames(item: string, users: any): any { - assert(item !== 'all' && item !== 'owner' && item !== 'anonymous' && item !== 'undefined' && item !== 'none', 'CONFIG: reserved uplink name: ' + item); + assert( + item !== 'all' && + item !== 'owner' && + item !== 'anonymous' && + item !== 'undefined' && + item !== 'none', + 'CONFIG: reserved uplink name: ' + item + ); assert(!item.match(/\s/), 'CONFIG: invalid uplink name: ' + item); assert(_.isNil(users[item]), 'CONFIG: duplicate uplink name: ' + item); users[item] = true; @@ -120,7 +142,9 @@ export function normalisePackageAccess(packages: LegacyPackageList): LegacyPacka normalizedPkgs[pkg].publish = normalizeUserList(packageAccess.publish); normalizedPkgs[pkg].proxy = normalizeUserList(packageAccess.proxy); // if unpublish is not defined, we set to false to fallback in publish access - normalizedPkgs[pkg].unpublish = _.isUndefined(packageAccess.unpublish) ? false : normalizeUserList(packageAccess.unpublish); + normalizedPkgs[pkg].unpublish = _.isUndefined(packageAccess.unpublish) + ? false + : normalizeUserList(packageAccess.unpublish); } } diff --git a/packages/utils/src/crypto-utils.ts b/packages/utils/src/crypto-utils.ts index 334bd4bb2..9f09c2cfc 100644 --- a/packages/utils/src/crypto-utils.ts +++ b/packages/utils/src/crypto-utils.ts @@ -56,7 +56,11 @@ export function generateRandomHexString(length = 8): string { * @param secretOrPrivateKey * @param options */ -export async function signPayload(payload: RemoteUser, secretOrPrivateKey: string, options: JWTSignOptions = {}): Promise { +export async function signPayload( + payload: RemoteUser, + secretOrPrivateKey: string, + options: JWTSignOptions = {} +): Promise { return new Promise(function (resolve, reject): Promise { return jwt.sign( payload, diff --git a/packages/utils/src/utils.ts b/packages/utils/src/utils.ts index 8c0046c00..8e60f90b0 100644 --- a/packages/utils/src/utils.ts +++ b/packages/utils/src/utils.ts @@ -8,10 +8,18 @@ import YAML from 'js-yaml'; import { Request } from 'express'; import sanitizyReadme from '@verdaccio/readme'; -import { APP_ERROR, DEFAULT_PORT, DEFAULT_DOMAIN, DEFAULT_PROTOCOL, CHARACTER_ENCODING, HEADERS, DIST_TAGS, DEFAULT_USER } from '@verdaccio/dev-commons'; +import { + APP_ERROR, + DEFAULT_PORT, + DEFAULT_DOMAIN, + DEFAULT_PROTOCOL, + CHARACTER_ENCODING, + HEADERS, + DIST_TAGS, + DEFAULT_USER, +} from '@verdaccio/dev-commons'; -import { Package, Version, Author } from '@verdaccio/types'; -import { StringValue } from '@verdaccio/dev-types'; +import { Package, Version, Author, StringValue } from '@verdaccio/types'; import { getConflict, @@ -122,7 +130,11 @@ export function validateMetadata(object: Package, name: string): Package { * Create base url for registry. * @return {String} base registry url */ -export function combineBaseUrl(protocol: string, host: string | void, prefix?: string | void): string { +export function combineBaseUrl( + protocol: string, + host: string | void, + prefix?: string | void +): string { const result = `${protocol}://${host}`; const prefixOnlySlash = prefix === '/'; @@ -153,7 +165,11 @@ export function extractTarballFromUrl(url: string): string { * @param {*} config * @return {String} a filtered package */ -export function convertDistRemoteToLocalTarballUrls(pkg: Package, req: Request, urlPrefix: string | void): Package { +export function convertDistRemoteToLocalTarballUrls( + pkg: Package, + req: Request, + urlPrefix: string | void +): Package { for (const ver in pkg.versions) { if (Object.prototype.hasOwnProperty.call(pkg.versions, ver)) { const distName = pkg.versions[ver].dist; @@ -171,7 +187,12 @@ export function convertDistRemoteToLocalTarballUrls(pkg: Package, req: Request, * @param {*} uri * @return {String} a parsed url */ -export function getLocalRegistryTarballUri(uri: string, pkgName: string, req: Request, urlPrefix: string | void): string { +export function getLocalRegistryTarballUri( + uri: string, + pkgName: string, + req: Request, + urlPrefix: string | void +): string { const currentHost = req.headers.host; if (!currentHost) { @@ -351,7 +372,11 @@ export function parseInterval(interval: any): number { return; } const m = x.match(/^((0|[1-9][0-9]*)(\.[0-9]+)?)(ms|s|m|h|d|w|M|y|)$/); - if (!m || parseIntervalTable[m[4]] >= last_suffix || (m[4] === '' && last_suffix !== Infinity)) { + if ( + !m || + parseIntervalTable[m[4]] >= last_suffix || + (m[4] === '' && last_suffix !== Infinity) + ) { throw Error('invalid interval: ' + interval); } last_suffix = parseIntervalTable[m[4]]; diff --git a/packages/utils/test/auth-utils.spec.ts b/packages/utils/test/auth-utils.spec.ts index 1a7f291ec..5fc033393 100644 --- a/packages/utils/test/auth-utils.spec.ts +++ b/packages/utils/test/auth-utils.spec.ts @@ -37,7 +37,15 @@ describe('Auth Utilities', () => { describe('createRemoteUser and createAnonymousRemoteUser', () => { test('should create a remote user with default groups', () => { expect(createRemoteUser('12345', ['foo', 'bar'])).toEqual({ - groups: ['foo', 'bar', ROLES.$ALL, ROLES.$AUTH, ROLES.DEPRECATED_ALL, ROLES.DEPRECATED_AUTH, ROLES.ALL], + groups: [ + 'foo', + 'bar', + ROLES.$ALL, + ROLES.$AUTH, + ROLES.DEPRECATED_ALL, + ROLES.DEPRECATED_AUTH, + ROLES.ALL, + ], name: '12345', real_groups: ['foo', 'bar'], }); @@ -62,75 +70,90 @@ describe('Auth Utilities', () => { }; // const type = 'access'; - test.each(['access', 'publish', 'unpublish'])('should restrict %s to anonymous users', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn() })( - createAnonymousRemoteUser(), - { - ...packageAccess, - [type]: ['foo'], - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).not.toBeNull(); - expect(allowed).toBeUndefined(); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])( + 'should restrict %s to anonymous users', + (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createAnonymousRemoteUser(), + { + ...packageAccess, + [type]: ['foo'], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).not.toBeNull(); + expect(allowed).toBeUndefined(); + } + ); + } + ); - test.each(['access', 'publish', 'unpublish'])('should allow %s to anonymous users', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn() })( - createAnonymousRemoteUser(), - { - ...packageAccess, - [type]: [ROLES.$ANONYMOUS], - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).toBeNull(); - expect(allowed).toBe(true); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])( + 'should allow %s to anonymous users', + (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createAnonymousRemoteUser(), + { + ...packageAccess, + [type]: [ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).toBeNull(); + expect(allowed).toBe(true); + } + ); + } + ); - test.each(['access', 'publish', 'unpublish'])('should allow %s only if user is anonymous if the logged user has groups', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn() })( - createRemoteUser('juan', ['maintainer', 'admin']), - { - ...packageAccess, - [type]: [ROLES.$ANONYMOUS], - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).not.toBeNull(); - expect(allowed).toBeUndefined(); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])( + 'should allow %s only if user is anonymous if the logged user has groups', + (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createRemoteUser('juan', ['maintainer', 'admin']), + { + ...packageAccess, + [type]: [ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).not.toBeNull(); + expect(allowed).toBeUndefined(); + } + ); + } + ); - test.each(['access', 'publish', 'unpublish'])('should allow %s only if user is anonymous match any other groups', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn() })( - createRemoteUser('juan', ['maintainer', 'admin']), - { - ...packageAccess, - [type]: ['admin', 'some-other-group', ROLES.$ANONYMOUS], - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).toBeNull(); - expect(allowed).toBe(true); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])( + 'should allow %s only if user is anonymous match any other groups', + (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createRemoteUser('juan', ['maintainer', 'admin']), + { + ...packageAccess, + [type]: ['admin', 'some-other-group', ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).toBeNull(); + expect(allowed).toBe(true); + } + ); + } + ); - test.each(['access', 'publish', 'unpublish'])('should not allow %s anonymous if other groups are defined and does not match', (type) => { - allow_action(type as ActionsAllowed, { trace: jest.fn() })( - createRemoteUser('juan', ['maintainer', 'admin']), - { - ...packageAccess, - [type]: ['bla-bla-group', 'some-other-group', ROLES.$ANONYMOUS], - }, - (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { - expect(error).not.toBeNull(); - expect(allowed).toBeUndefined(); - } - ); - }); + test.each(['access', 'publish', 'unpublish'])( + 'should not allow %s anonymous if other groups are defined and does not match', + (type) => { + allow_action(type as ActionsAllowed, { trace: jest.fn() })( + createRemoteUser('juan', ['maintainer', 'admin']), + { + ...packageAccess, + [type]: ['bla-bla-group', 'some-other-group', ROLES.$ANONYMOUS], + }, + (error: VerdaccioError | null, allowed: AllowActionCallbackResponse) => { + expect(error).not.toBeNull(); + expect(allowed).toBeUndefined(); + } + ); + } + ); }); }); describe('createSessionToken', () => { diff --git a/packages/utils/test/config-utils.spec.ts b/packages/utils/test/config-utils.spec.ts index 0be0b2b3a..711e78663 100644 --- a/packages/utils/test/config-utils.spec.ts +++ b/packages/utils/test/config-utils.spec.ts @@ -5,7 +5,13 @@ import { PACKAGE_ACCESS } from '@verdaccio/dev-commons'; import { spliceURL } from '../src/string'; import { parseConfigFile } from '../src/utils'; -import { getMatchedPackagesSpec, hasProxyTo, normalisePackageAccess, sanityCheckUplinksProps, uplinkSanityCheck } from '../src/config-utils'; +import { + getMatchedPackagesSpec, + hasProxyTo, + normalisePackageAccess, + sanityCheckUplinksProps, + uplinkSanityCheck, +} from '../src/config-utils'; describe('Config Utilities', () => { const parseConfigurationFile = (conf) => { @@ -17,7 +23,9 @@ describe('Config Utilities', () => { describe('uplinkSanityCheck', () => { test('should test basic conversion', () => { - const uplinks = uplinkSanityCheck(parseConfigFile(parseConfigurationFile('uplink-basic')).uplinks); + const uplinks = uplinkSanityCheck( + parseConfigFile(parseConfigurationFile('uplink-basic')).uplinks + ); expect(Object.keys(uplinks)).toContain('server1'); expect(Object.keys(uplinks)).toContain('server2'); }); @@ -199,7 +207,9 @@ describe('Config Utilities', () => { describe('hasProxyTo', () => { test('should test basic config', () => { - const packages = normalisePackageAccess(parseConfigFile(parseConfigurationFile('pkgs-basic')).packages); + const packages = normalisePackageAccess( + parseConfigFile(parseConfigurationFile('pkgs-basic')).packages + ); // react expect(hasProxyTo('react', 'facebook', packages)).toBeFalsy(); expect(hasProxyTo('react', 'google', packages)).toBeFalsy(); @@ -214,7 +224,9 @@ describe('Config Utilities', () => { }); test('should test resolve based on custom package access', () => { - const packages = normalisePackageAccess(parseConfigFile(parseConfigurationFile('pkgs-custom')).packages); + const packages = normalisePackageAccess( + parseConfigFile(parseConfigurationFile('pkgs-custom')).packages + ); // react expect(hasProxyTo('react', 'facebook', packages)).toBeTruthy(); expect(hasProxyTo('react', 'google', packages)).toBeFalsy(); @@ -229,7 +241,9 @@ describe('Config Utilities', () => { }); test('should not resolve any proxy', () => { - const packages = normalisePackageAccess(parseConfigFile(parseConfigurationFile('pkgs-empty')).packages); + const packages = normalisePackageAccess( + parseConfigFile(parseConfigurationFile('pkgs-empty')).packages + ); // react expect(hasProxyTo('react', 'npmjs', packages)).toBeFalsy(); expect(hasProxyTo('react', 'npmjs', packages)).toBeFalsy(); diff --git a/packages/utils/test/utils.spec.ts b/packages/utils/test/utils.spec.ts index 92d777f0f..ef97def2a 100644 --- a/packages/utils/test/utils.spec.ts +++ b/packages/utils/test/utils.spec.ts @@ -136,7 +136,9 @@ describe('Utilities', () => { get: () => 'http', protocol: 'http', }); - expect(convertDist.versions['1.0.0'].dist.tarball).toEqual(convertDist.versions['1.0.0'].dist.tarball); + expect(convertDist.versions['1.0.0'].dist.tarball).toEqual( + convertDist.versions['1.0.0'].dist.tarball + ); }); }); @@ -209,7 +211,9 @@ describe('Utilities', () => { expect(combineBaseUrl('http', 'domain', '')).toEqual('http://domain'); expect(combineBaseUrl('http', 'domain', '/')).toEqual('http://domain'); expect(combineBaseUrl('http', 'domain', '/prefix/')).toEqual('http://domain/prefix'); - expect(combineBaseUrl('http', 'domain', '/prefix/deep')).toEqual('http://domain/prefix/deep'); + expect(combineBaseUrl('http', 'domain', '/prefix/deep')).toEqual( + 'http://domain/prefix/deep' + ); expect(combineBaseUrl('http', 'domain', 'only-prefix')).toEqual('only-prefix'); }); }); @@ -368,7 +372,9 @@ describe('Utilities', () => { expect(parseReadme('testPackage', randomText)).toEqual('

%%%%%**##==

'); expect(parseReadme('testPackage', simpleText)).toEqual('

simple text

'); - expect(parseReadme('testPackage', randomTextMarkdown)).toEqual('

simple text

\n

markdown

'); + expect(parseReadme('testPackage', randomTextMarkdown)).toEqual( + '

simple text

\n

markdown

' + ); }); test('should show error for no readme data', () => { @@ -377,8 +383,13 @@ describe('Utilities', () => { const logger = { error: loggerError, }; - expect(parseReadme('testPackage', noData, logger)).toEqual('

ERROR: No README data found!

'); - expect(loggerError).toHaveBeenCalledWith({ packageName: 'testPackage' }, '@{packageName}: No readme found'); + expect(parseReadme('testPackage', noData, logger)).toEqual( + '

ERROR: No README data found!

' + ); + expect(loggerError).toHaveBeenCalledWith( + { packageName: 'testPackage' }, + '@{packageName}: No readme found' + ); }); }); diff --git a/packages/verdaccio/jest.config.js b/packages/verdaccio/jest.config.js index c755212b1..93d85215f 100644 --- a/packages/verdaccio/jest.config.js +++ b/packages/verdaccio/jest.config.js @@ -29,5 +29,10 @@ module.exports = { '/.vscode/', ], testPathIgnorePatterns: ['__snapshots__', '/build'], - coveragePathIgnorePatterns: ['node_modules', 'fixtures', '/src/api/debug', '/test'], + coveragePathIgnorePatterns: [ + 'node_modules', + 'fixtures', + '/src/api/debug', + '/test', + ], }; diff --git a/packages/verdaccio/test/functional/adduser/adduser.js b/packages/verdaccio/test/functional/adduser/adduser.js index 6f38665b2..c772cdc97 100644 --- a/packages/verdaccio/test/functional/adduser/adduser.js +++ b/packages/verdaccio/test/functional/adduser/adduser.js @@ -22,7 +22,10 @@ export default function (server) { }); test('should not register more users', () => { - return server.auth(String(Math.random()), String(Math.random())).status(HTTP_STATUS.CONFLICT).body_error(API_ERROR.MAX_USERS_REACHED); + return server + .auth(String(Math.random()), String(Math.random())) + .status(HTTP_STATUS.CONFLICT) + .body_error(API_ERROR.MAX_USERS_REACHED); }); }); } diff --git a/packages/verdaccio/test/functional/basic/basic.ts b/packages/verdaccio/test/functional/basic/basic.ts index 796a1e76d..4d5ebccb7 100644 --- a/packages/verdaccio/test/functional/basic/basic.ts +++ b/packages/verdaccio/test/functional/basic/basic.ts @@ -3,7 +3,13 @@ import path from 'path'; import { createTarballHash } from '@verdaccio/utils'; import { HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons'; -import { CREDENTIALS, DOMAIN_SERVERS, PORT_SERVER_1, PORT_SERVER_2, TARBALL } from '../config.functional'; +import { + CREDENTIALS, + DOMAIN_SERVERS, + PORT_SERVER_1, + PORT_SERVER_2, + TARBALL, +} from '../config.functional'; import whoIam from './whoIam'; import ping from './ping'; import fixturePkg from '../fixtures/package'; @@ -52,16 +58,27 @@ export default function (server: any, server2: any) { }); test('uploading incomplete tarball', () => { - return server.putTarballIncomplete(PKG_NAME, 'blahblah1', readfile('../fixtures/binary'), 3000); + return server.putTarballIncomplete( + PKG_NAME, + 'blahblah1', + readfile('../fixtures/binary'), + 3000 + ); }); describe('publishing package', () => { beforeAll(function () { - return server.putTarball(PKG_NAME, TARBALL, readfile('../fixtures/binary')).status(HTTP_STATUS.CREATED).body_ok(/.*/); + return server + .putTarball(PKG_NAME, TARBALL, readfile('../fixtures/binary')) + .status(HTTP_STATUS.CREATED) + .body_ok(/.*/); }); beforeAll(function () { - return server.putTarball('testpkg-single-tarball', 'single', readfile('../fixtures/binary')).status(HTTP_STATUS.CREATED).body_ok(/.*/); + return server + .putTarball('testpkg-single-tarball', 'single', readfile('../fixtures/binary')) + .status(HTTP_STATUS.CREATED) + .body_ok(/.*/); }); afterAll(function () { @@ -87,7 +104,9 @@ export default function (server: any, server2: any) { // testexp-incomplete test('remove existing single tarball', () => { - return server.removeSingleTarball('testpkg-single-tarball', 'single').status(HTTP_STATUS.CREATED); + return server + .removeSingleTarball('testpkg-single-tarball', 'single') + .status(HTTP_STATUS.CREATED); }); // testexp-incomplete @@ -115,7 +134,9 @@ export default function (server: any, server2: any) { beforeAll(function () { const pkg = getPackage(PKG_NAME); - pkg.dist.shasum = createTarballHash().update(readfile('../fixtures/binary')).digest('hex'); + pkg.dist.shasum = createTarballHash() + .update(readfile('../fixtures/binary')) + .digest('hex'); return server .putVersion(PKG_NAME, PKG_VERSION, pkg) .status(HTTP_STATUS.CREATED) @@ -124,7 +145,10 @@ export default function (server: any, server2: any) { describe('should download a package', () => { beforeAll(function () { - return server.auth(CREDENTIALS.user, CREDENTIALS.password).status(HTTP_STATUS.CREATED).body_ok(new RegExp(CREDENTIALS.user)); + return server + .auth(CREDENTIALS.user, CREDENTIALS.password) + .status(HTTP_STATUS.CREATED) + .body_ok(new RegExp(CREDENTIALS.user)); }); test('should download a newly created package from server1', () => { @@ -134,7 +158,9 @@ export default function (server: any, server2: any) { .then(function (body) { expect(body.name).toEqual(PKG_NAME); expect(body.versions[PKG_VERSION].name).toEqual(PKG_NAME); - expect(body.versions[PKG_VERSION].dist.tarball).toEqual(`http://${DOMAIN_SERVERS}:${PORT_SERVER_1}/${PKG_NAME}/-/${TARBALL}`); + expect(body.versions[PKG_VERSION].dist.tarball).toEqual( + `http://${DOMAIN_SERVERS}:${PORT_SERVER_1}/${PKG_NAME}/-/${TARBALL}` + ); expect(body[DIST_TAGS]).toEqual({ latest: PKG_VERSION, }); @@ -148,7 +174,9 @@ export default function (server: any, server2: any) { .then(function (body) { expect(body.name).toEqual(PKG_NAME); expect(body.versions[PKG_VERSION].name).toEqual(PKG_NAME); - expect(body.versions[PKG_VERSION].dist.tarball).toEqual(`http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/${PKG_NAME}/-/${TARBALL}`); + expect(body.versions[PKG_VERSION].dist.tarball).toEqual( + `http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/${PKG_NAME}/-/${TARBALL}` + ); expect(body[DIST_TAGS]).toEqual({ latest: PKG_VERSION, }); diff --git a/packages/verdaccio/test/functional/notifications/notify.ts b/packages/verdaccio/test/functional/notifications/notify.ts index 2fa8b15f9..051dc2808 100644 --- a/packages/verdaccio/test/functional/notifications/notify.ts +++ b/packages/verdaccio/test/functional/notifications/notify.ts @@ -51,7 +51,9 @@ export default function (express) { notify(metadata, config, publisherInfo, 'foo').then( function (body) { const jsonBody = parseBody(body); - expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); + expect( + `New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.` + ).toBe(jsonBody.message); done(); }, function (err) { @@ -76,7 +78,9 @@ export default function (express) { notify(metadata, configMultipleHeader, publisherInfo).then( function (body) { const jsonBody = parseBody(body); - expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); + expect( + `New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.` + ).toBe(jsonBody.message); done(); }, function (err) { @@ -111,7 +115,9 @@ export default function (express) { function (body) { body.forEach(function (notification) { const jsonBody = parseBody(notification); - expect(`New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.`).toBe(jsonBody.message); + expect( + `New package published: * ${metadata.name}*. Publisher name: * ${publisherInfo.name} *.` + ).toBe(jsonBody.message); }); done(); }, @@ -154,7 +160,9 @@ export default function (express) { notify(metadata, config, publisherInfo).then( function (body) { const jsonBody = parseBody(body); - expect(`New package published: * ${metadata.name}*. Publisher name: * ${metadata.publisher.name} *.`).toBe(jsonBody.message); + expect( + `New package published: * ${metadata.name}*. Publisher name: * ${metadata.publisher.name} *.` + ).toBe(jsonBody.message); done(); }, function (err) { diff --git a/packages/verdaccio/test/functional/package/scoped.ts b/packages/verdaccio/test/functional/package/scoped.ts index 8b46cb29f..71f4ac361 100644 --- a/packages/verdaccio/test/functional/package/scoped.ts +++ b/packages/verdaccio/test/functional/package/scoped.ts @@ -53,7 +53,9 @@ export default function (server, server2) { .then(function (body) { expect(body.name).toBe(SCOPE); expect(body.versions[PKG_VERSION].name).toBe(SCOPE); - expect(body.versions[PKG_VERSION].dist.tarball).toBe(`http://${DOMAIN_SERVERS}:${port}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz`); + expect(body.versions[PKG_VERSION].dist.tarball).toBe( + `http://${DOMAIN_SERVERS}:${port}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz` + ); expect(body[DIST_TAGS]).toEqual({ latest: PKG_VERSION }); }); @@ -70,7 +72,9 @@ export default function (server, server2) { .status(HTTP_STATUS.OK) .then(function (body) { expect(body.name).toEqual(SCOPE); - expect(body.dist.tarball).toEqual(`http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz`); + expect(body.dist.tarball).toEqual( + `http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz` + ); }); }); }); diff --git a/packages/verdaccio/test/functional/performance/race.ts b/packages/verdaccio/test/functional/performance/race.ts index cbac801a4..3f69eefbe 100644 --- a/packages/verdaccio/test/functional/performance/race.ts +++ b/packages/verdaccio/test/functional/performance/race.ts @@ -60,7 +60,10 @@ export default function (server) { failCount++; } - if (resp.statusCode === HTTP_STATUS.SERVICE_UNAVAILABLE && ~body.error.indexOf(UNAVAILABLE)) { + if ( + resp.statusCode === HTTP_STATUS.SERVICE_UNAVAILABLE && + ~body.error.indexOf(UNAVAILABLE) + ) { failCount++; } }); @@ -108,7 +111,10 @@ export default function (server) { if (response.statusCode === HTTP_STATUS.CONFLICT && ~body.error.indexOf(PRESENT)) { failcount++; } - if (response.statusCode === HTTP_STATUS.SERVICE_UNAVAILABLE && ~body.error.indexOf(UNAVAILABLE)) { + if ( + response.statusCode === HTTP_STATUS.SERVICE_UNAVAILABLE && + ~body.error.indexOf(UNAVAILABLE) + ) { failcount++; } }); diff --git a/packages/verdaccio/test/functional/plugins/auth.ts b/packages/verdaccio/test/functional/plugins/auth.ts index 1397bc133..b31aa0104 100644 --- a/packages/verdaccio/test/functional/plugins/auth.ts +++ b/packages/verdaccio/test/functional/plugins/auth.ts @@ -40,11 +40,21 @@ export default function (server2) { describe('plugin authentication', () => { describe('test users authentication', () => { test('should not authenticate user1 with wrong password', () => { - return requestAuthFail(USER1, WRONG_PASSWORD, "i don't like your password", HTTP_STATUS.UNAUTHORIZED); + return requestAuthFail( + USER1, + WRONG_PASSWORD, + "i don't like your password", + HTTP_STATUS.UNAUTHORIZED + ); }); test('should not authenticate user2 with wrong password', () => { - return requestAuthFail(USER2, WRONG_PASSWORD, "i don't like your password", HTTP_STATUS.UNAUTHORIZED); + return requestAuthFail( + USER2, + WRONG_PASSWORD, + "i don't like your password", + HTTP_STATUS.UNAUTHORIZED + ); }); test('should right user2 password handled by plugin', () => { @@ -59,37 +69,61 @@ export default function (server2) { describe('test package access authorization', () => { describe(`access with user ${USER1} on server2`, () => { beforeAll(function () { - return server2.auth(USER1, CORRECT_PASSWORD).status(HTTP_STATUS.CREATED).body_ok(new RegExp(USER1)); + return server2 + .auth(USER1, CORRECT_PASSWORD) + .status(HTTP_STATUS.CREATED) + .body_ok(new RegExp(USER1)); }); test(`should fails (404) on access ${UNEXISTING_PKG_NAME}`, () => { - return server2.getPackage(UNEXISTING_PKG_NAME).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); + return server2 + .getPackage(UNEXISTING_PKG_NAME) + .status(HTTP_STATUS.NOT_FOUND) + .body_error(API_ERROR.NO_PACKAGE); }); test(`should fails (403) access ${ONLY_ACCESS_BY_USER_2}`, () => { - return server2.getPackage(ONLY_ACCESS_BY_USER_2).status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); + return server2 + .getPackage(ONLY_ACCESS_BY_USER_2) + .status(HTTP_STATUS.FORBIDDEN) + .body_error(API_ERROR.NOT_ALLOWED); }); test(`should fails (404) access ${AUTH_PKG_ACCESS_NAME}`, () => { - return server2.getPackage(AUTH_PKG_ACCESS_NAME).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); + return server2 + .getPackage(AUTH_PKG_ACCESS_NAME) + .status(HTTP_STATUS.NOT_FOUND) + .body_error(API_ERROR.NO_PACKAGE); }); }); describe(`access with user ${USER2} on server2`, () => { beforeAll(function () { - return server2.auth(USER2, CORRECT_PASSWORD).status(HTTP_STATUS.CREATED).body_ok(new RegExp(USER2)); + return server2 + .auth(USER2, CORRECT_PASSWORD) + .status(HTTP_STATUS.CREATED) + .body_ok(new RegExp(USER2)); }); test(`should fails (403) on access ${UNEXISTING_PKG_NAME}`, () => { - return server2.getPackage(UNEXISTING_PKG_NAME).status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); + return server2 + .getPackage(UNEXISTING_PKG_NAME) + .status(HTTP_STATUS.FORBIDDEN) + .body_error(API_ERROR.NOT_ALLOWED); }); test(`should fails (403) on access ${DENY_PKG_NAME}`, () => { - return server2.getPackage(DENY_PKG_NAME).status(HTTP_STATUS.FORBIDDEN).body_error(API_ERROR.NOT_ALLOWED); + return server2 + .getPackage(DENY_PKG_NAME) + .status(HTTP_STATUS.FORBIDDEN) + .body_error(API_ERROR.NOT_ALLOWED); }); test(`should fails (404) access ${AUTH_PKG_ACCESS_NAME}`, () => { - return server2.getPackage(AUTH_PKG_ACCESS_NAME).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); + return server2 + .getPackage(AUTH_PKG_ACCESS_NAME) + .status(HTTP_STATUS.NOT_FOUND) + .body_error(API_ERROR.NO_PACKAGE); }); }); }); diff --git a/packages/verdaccio/test/functional/sanity/mirror.ts b/packages/verdaccio/test/functional/sanity/mirror.ts index 644ab93cd..bc78fd869 100644 --- a/packages/verdaccio/test/functional/sanity/mirror.ts +++ b/packages/verdaccio/test/functional/sanity/mirror.ts @@ -25,7 +25,10 @@ export default function (server, server2) { describe(`testing mirror for ${pkg}`, () => { beforeAll(function () { - return server2.putPackage(pkg, generatePkg(pkg)).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); + return server2 + .putPackage(pkg, generatePkg(pkg)) + .status(HTTP_STATUS.CREATED) + .body_ok(API_MESSAGE.PKG_CREATED); }); test(prefix + 'creating new package', () => {}); @@ -46,7 +49,10 @@ export default function (server, server2) { describe('should put a tarball', () => { beforeAll(function () { - return server2.putTarball(pkg, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); + return server2 + .putTarball(pkg, TARBALL, getBinary()) + .status(HTTP_STATUS.CREATED) + .body_ok(/.*/); }); test(`should ${prefix} uploading new tarball`, () => {}); diff --git a/packages/verdaccio/test/functional/sanity/nullstorage.ts b/packages/verdaccio/test/functional/sanity/nullstorage.ts index 57ab39b8f..167a95c05 100644 --- a/packages/verdaccio/test/functional/sanity/nullstorage.ts +++ b/packages/verdaccio/test/functional/sanity/nullstorage.ts @@ -18,7 +18,10 @@ export default function (server, server2) { describe('should test a scenario when tarball is being fetch from uplink', () => { describe(`should check whether ${PKG_NAME} is on server1`, () => { test('should fails on fetch non-existent package on server1', () => { - return server.getPackage('test-nullstorage-nonexist').status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); + return server + .getPackage('test-nullstorage-nonexist') + .status(HTTP_STATUS.NOT_FOUND) + .body_error(API_ERROR.NO_PACKAGE); }); }); @@ -40,7 +43,10 @@ export default function (server, server2) { describe(`should succesfully publish ${PKG_NAME} package on server2`, () => { beforeAll(function () { - return server2.putTarball(PKG_NAME, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); + return server2 + .putTarball(PKG_NAME, TARBALL, getBinary()) + .status(HTTP_STATUS.CREATED) + .body_ok(/.*/); }); beforeAll(function () { @@ -72,7 +78,9 @@ export default function (server, server2) { .then(function (body) { expect(body.name).toBe(PKG_NAME); expect(body.versions[PKG_VERSION].name).toBe(PKG_NAME); - expect(body.versions[PKG_VERSION].dist.tarball).toBe(`http://${DOMAIN_SERVERS}:${PORT_SERVER_1}/${PKG_NAME}/-/${TARBALL}`); + expect(body.versions[PKG_VERSION].dist.tarball).toBe( + `http://${DOMAIN_SERVERS}:${PORT_SERVER_1}/${PKG_NAME}/-/${TARBALL}` + ); expect(body[DIST_TAGS]).toEqual({ latest: PKG_VERSION }); }); }); diff --git a/packages/verdaccio/test/functional/sanity/racycrash.ts b/packages/verdaccio/test/functional/sanity/racycrash.ts index 634f5f5ad..87a8b703a 100644 --- a/packages/verdaccio/test/functional/sanity/racycrash.ts +++ b/packages/verdaccio/test/functional/sanity/racycrash.ts @@ -59,7 +59,9 @@ export default function (server, express) { res.socket.destroy(); }; - return server.request({ uri: '/testexp-racycrash/-/test.tar.gz' }).body_error(API_ERROR.INTERNAL_SERVER_ERROR); + return server + .request({ uri: '/testexp-racycrash/-/test.tar.gz' }) + .body_error(API_ERROR.INTERNAL_SERVER_ERROR); }); }); } diff --git a/packages/verdaccio/test/functional/sanity/security.ts b/packages/verdaccio/test/functional/sanity/security.ts index 389efe4d6..6c44af8fd 100644 --- a/packages/verdaccio/test/functional/sanity/security.ts +++ b/packages/verdaccio/test/functional/sanity/security.ts @@ -39,12 +39,17 @@ export default function (server) { }); test('should fails on fetch silly things - reading #1', () => { - return server.request({ uri: '/testpkg-sec/-/../../../../../../../../etc/passwd' }).status(HTTP_STATUS.NOT_FOUND); + return server + .request({ uri: '/testpkg-sec/-/../../../../../../../../etc/passwd' }) + .status(HTTP_STATUS.NOT_FOUND); }); test('should fails on fetch silly things - reading #2', () => { return server - .request({ uri: '/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd' }) + .request({ + uri: + '/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd', + }) .status(HTTP_STATUS.FORBIDDEN) .body_error(/invalid filename/); }); diff --git a/packages/verdaccio/test/functional/scenarios/gh29.ts b/packages/verdaccio/test/functional/scenarios/gh29.ts index 90c55a67a..1078c67af 100644 --- a/packages/verdaccio/test/functional/scenarios/gh29.ts +++ b/packages/verdaccio/test/functional/scenarios/gh29.ts @@ -44,7 +44,10 @@ export default function (server, server2) { describe('tarball', () => { beforeAll(function () { - return server.putTarball(pkgName, TARBALL, readfile(binary)).status(HTTP_STATUS.CREATED).body_ok(/.*/); + return server + .putTarball(pkgName, TARBALL, readfile(binary)) + .status(HTTP_STATUS.CREATED) + .body_ok(/.*/); }); test('uploading new tarball / srv1', () => {}); diff --git a/packages/verdaccio/test/functional/search/simple.search.ts b/packages/verdaccio/test/functional/search/simple.search.ts index 98db389d9..3d95bfbd0 100644 --- a/packages/verdaccio/test/functional/search/simple.search.ts +++ b/packages/verdaccio/test/functional/search/simple.search.ts @@ -6,7 +6,10 @@ export default function (server, server2, express) { const PKG_NAME = 'testpkg-search'; beforeAll(function () { - return server.putPackage(PKG_NAME, pkgExample).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); + return server + .putPackage(PKG_NAME, pkgExample) + .status(HTTP_STATUS.CREATED) + .body_ok(API_MESSAGE.PKG_CREATED); }); describe('should test simple search', () => { diff --git a/packages/verdaccio/test/functional/tags/addtag.ts b/packages/verdaccio/test/functional/tags/addtag.ts index c1f6c01a0..267edcd9a 100644 --- a/packages/verdaccio/test/functional/tags/addtag.ts +++ b/packages/verdaccio/test/functional/tags/addtag.ts @@ -10,7 +10,10 @@ export default function (server) { const PKG_VERSION = '0.0.1'; test('should fails on add tag to non existing package', () => { - return server.addTag(PKG_NAME, 'tagtagtag', PKG_VERSION).status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.NO_PACKAGE); + return server + .addTag(PKG_NAME, 'tagtagtag', PKG_VERSION) + .status(HTTP_STATUS.NOT_FOUND) + .body_error(API_ERROR.NO_PACKAGE); }); describe('should test add tag to a package', () => { @@ -30,7 +33,10 @@ export default function (server) { describe('should test valid formats tags', () => { test('should fails on add a tag that do not exist', () => { - return server.addTag(PKG_NAME, 'tagtagtag', '4.0.0-no-exist').status(HTTP_STATUS.NOT_FOUND).body_error(API_ERROR.VERSION_NOT_EXIST); + return server + .addTag(PKG_NAME, 'tagtagtag', '4.0.0-no-exist') + .status(HTTP_STATUS.NOT_FOUND) + .body_error(API_ERROR.VERSION_NOT_EXIST); }); test('should add tag succesfully minor version', () => { diff --git a/packages/verdaccio/test/functional/tags/dist-tags-merge.ts b/packages/verdaccio/test/functional/tags/dist-tags-merge.ts index e0ce7a7f0..63a5ad99b 100644 --- a/packages/verdaccio/test/functional/tags/dist-tags-merge.ts +++ b/packages/verdaccio/test/functional/tags/dist-tags-merge.ts @@ -11,7 +11,10 @@ export default function (server, server2, server3) { const PKG_VERSION = '0.0.1'; beforeAll(function () { - return server.putPackage(PKG_NAME, pkgExample).status(HTTP_STATUS.CREATED).body_ok(API_MESSAGE.PKG_CREATED); + return server + .putPackage(PKG_NAME, pkgExample) + .status(HTTP_STATUS.CREATED) + .body_ok(API_MESSAGE.PKG_CREATED); }); describe('should check sha integrity', () => { @@ -25,8 +28,10 @@ export default function (server, server2, server3) { }); }; - test('server1 should match with sha key from published package', () => matchTarBallSha(server)); - test('server2 should match with sha key from published package', () => matchTarBallSha(server2)); + test('server1 should match with sha key from published package', () => + matchTarBallSha(server)); + test('server2 should match with sha key from published package', () => + matchTarBallSha(server2)); }); describe('should match dist-tags', () => { @@ -40,7 +45,9 @@ export default function (server, server2, server3) { expect(body.time[PKG_VERSION]).toBeDefined(); expect(body.time).toBeDefined(); expect(body.versions[PKG_VERSION].name).toBe(PKG_NAME); - expect(body.versions[PKG_VERSION].dist.tarball).toBe(`http://${DOMAIN_SERVERS}:${port}/${PKG_NAME}/-/${PKG_NAME}-${PKG_VERSION}.tgz`); + expect(body.versions[PKG_VERSION].dist.tarball).toBe( + `http://${DOMAIN_SERVERS}:${port}/${PKG_NAME}/-/${PKG_NAME}-${PKG_VERSION}.tgz` + ); expect(body[DIST_TAGS]).toEqual({ foo: PKG_VERSION, latest: PKG_VERSION }); }); }; diff --git a/packages/verdaccio/test/functional/uplinks/cache.ts b/packages/verdaccio/test/functional/uplinks/cache.ts index 19dd585ad..d057786c0 100644 --- a/packages/verdaccio/test/functional/uplinks/cache.ts +++ b/packages/verdaccio/test/functional/uplinks/cache.ts @@ -31,7 +31,10 @@ export default function (server, server2, server3) { }); beforeAll(function () { - return server.putTarball(PKG_GH131, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); + return server + .putTarball(PKG_GH131, TARBALL, getBinary()) + .status(HTTP_STATUS.CREATED) + .body_ok(/.*/); }); beforeAll(function () { @@ -61,7 +64,10 @@ export default function (server, server2, server3) { }); beforeAll(function () { - return server2.putTarball(PKG_GH1312, TARBALL, getBinary()).status(HTTP_STATUS.CREATED).body_ok(/.*/); + return server2 + .putTarball(PKG_GH1312, TARBALL, getBinary()) + .status(HTTP_STATUS.CREATED) + .body_ok(/.*/); }); beforeAll(function () { diff --git a/packages/verdaccio/test/types-test/plugins/auth/example.auth.plugin.ts b/packages/verdaccio/test/types-test/plugins/auth/example.auth.plugin.ts index eaaf7eef7..e36ea85a5 100644 --- a/packages/verdaccio/test/types-test/plugins/auth/example.auth.plugin.ts +++ b/packages/verdaccio/test/types-test/plugins/auth/example.auth.plugin.ts @@ -10,7 +10,7 @@ import { IPluginAuth, RemoteUser, Logger, - PluginOptions + PluginOptions, } from '@verdaccio/types'; class ExampleAuthPlugin implements IPluginAuth<{}> { @@ -22,7 +22,7 @@ class ExampleAuthPlugin implements IPluginAuth<{}> { this.logger = options.logger; } - adduser(user: string, password: string, cb: Callback): void { // pragma: allowlist secret + adduser(user: string, password: string, cb: Callback): void { cb(); } @@ -30,7 +30,7 @@ class ExampleAuthPlugin implements IPluginAuth<{}> { cb(); } - authenticate(user: string, password: string, cb: Callback): void { // pragma: allowlist secret + authenticate(user: string, password: string, cb: Callback): void { cb(); } @@ -79,12 +79,12 @@ class ExampleAuthCustomPlugin implements IPluginAuth<{}> { const config1: AppConfig = new Config({ storage: './storage', - self_path: '/home/sotrage' + self_path: '/home/sotrage', }); const options: PluginOptions<{}> = { config: config1, - logger: logger.child({sub: 'out'}) + logger: logger.child(), }; const auth = new ExampleAuthPlugin(config1, options); @@ -92,7 +92,7 @@ const authSub = new ExampleAuthCustomPlugin(config1, options); const remoteUser: RemoteUser = { groups: [], real_groups: [], - name: 'test' + name: 'test', }; auth.authenticate('user', 'pass', () => {}); diff --git a/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts b/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts index c15a2fbf5..f3742a733 100644 --- a/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts +++ b/packages/verdaccio/test/types-test/plugins/middleware/example.middleware.plugin.ts @@ -7,9 +7,16 @@ import { generatePackageTemplate } from '@verdaccio/store'; import { readFile } from '../../../functional/lib/test.utils'; import { Package } from '@verdaccio/types'; -const readMetadata = (fileName: string): Package => JSON.parse(readFile(`../../unit/partials/${fileName}`).toString()) as Package; +const readMetadata = (fileName: string): Package => + JSON.parse(readFile(`../../unit/partials/${fileName}`).toString()) as Package; -import { Config as AppConfig, IPluginMiddleware, IStorageManager, RemoteUser, IBasicAuth } from '@verdaccio/types'; +import { + Config as AppConfig, + IPluginMiddleware, + IStorageManager, + RemoteUser, + IBasicAuth, +} from '@verdaccio/types'; import { IUploadTarball, IReadTarball } from '@verdaccio/streams'; import { generateVersion } from '../../../unit/__helper/utils'; diff --git a/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts b/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts index 763c0c506..ec551ed22 100644 --- a/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts +++ b/packages/verdaccio/test/types-test/plugins/storage/example.storage.plugin.ts @@ -1,6 +1,15 @@ // this file is not aim to be tested, just to check typescript definitions -import { Callback, Config as AppConfig, Logger, Package, Token, TokenFilter, IUploadTarball, IReadTarball } from '@verdaccio/types'; +import { + Callback, + Config as AppConfig, + Logger, + Package, + Token, + TokenFilter, + IUploadTarball, + IReadTarball, +} from '@verdaccio/types'; import { IPluginStorage, IPackageStorageManager, IPackageStorage } from '@verdaccio/types'; import { UploadTarball, ReadTarball } from '@verdaccio/streams'; @@ -18,7 +27,13 @@ class PackageStorage implements IPackageStorageManager { this.logger = logger; } - updatePackage(name: string, updateHandler: Callback, onWrite: Callback, transformPackage: Function, onEnd: Callback) { + updatePackage( + name: string, + updateHandler: Callback, + onWrite: Callback, + transformPackage: Function, + onEnd: Callback + ) { onEnd(); } diff --git a/packages/verdaccio/test/unit/__helper/api.ts b/packages/verdaccio/test/unit/__helper/api.ts index 701a3b9f9..fc08a9783 100644 --- a/packages/verdaccio/test/unit/__helper/api.ts +++ b/packages/verdaccio/test/unit/__helper/api.ts @@ -16,9 +16,17 @@ import { getTaggedVersionFromPackage } from './expects'; // - Encourage using constants or create new ones if it's needed // - // @ts-ignore or any is fine if there is no other way -export function putPackage(request: any, pkgName: string, publishMetadata: Package, token?: string): Promise { +export function putPackage( + request: any, + pkgName: string, + publishMetadata: Package, + token?: string +): Promise { return new Promise((resolve) => { - let put = request.put(pkgName).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON).send(JSON.stringify(publishMetadata)); + let put = request + .put(pkgName) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON) + .send(JSON.stringify(publishMetadata)); if (_.isEmpty(token) === false) { expect(token).toBeDefined(); @@ -37,7 +45,9 @@ export function putPackage(request: any, pkgName: string, publishMetadata: Packa export function deletePackage(request: any, pkgName: string, token?: string): Promise { return new Promise((resolve) => { - let del = request.put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`).set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); + let del = request + .put(`/${encodeScopedUri(pkgName)}/-rev/${generateRandomHexString(8)}`) + .set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); if (_.isNil(token) === false) { del.set(HEADERS.AUTHORIZATION, buildToken(TOKEN_BEARER, token as string)); @@ -52,7 +62,12 @@ export function deletePackage(request: any, pkgName: string, token?: string): Pr }); } -export function getPackage(request: any, token: string, pkgName: string, statusCode: number = HTTP_STATUS.OK): Promise { +export function getPackage( + request: any, + token: string, + pkgName: string, + statusCode: number = HTTP_STATUS.OK +): Promise { return new Promise((resolve) => { let getRequest = request.get(`/${pkgName}`); @@ -70,7 +85,13 @@ export function getPackage(request: any, token: string, pkgName: string, statusC }); } -export function loginUserToken(request: any, user: string, credentials: any, token: string, statusCode: number = HTTP_STATUS.CREATED): Promise { +export function loginUserToken( + request: any, + user: string, + credentials: any, + token: string, + statusCode: number = HTTP_STATUS.CREATED +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -85,7 +106,12 @@ export function loginUserToken(request: any, user: string, credentials: any, tok }); } -export function addUser(request: any, user: string, credentials: any, statusCode: number = HTTP_STATUS.CREATED): Promise { +export function addUser( + request: any, + user: string, + credentials: any, + statusCode: number = HTTP_STATUS.CREATED +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -112,7 +138,11 @@ export async function getNewToken(request: any, credentials: any): Promise { +export function getProfile( + request: any, + token: string, + statusCode: number = HTTP_STATUS.OK +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -126,7 +156,12 @@ export function getProfile(request: any, token: string, statusCode: number = HTT }); } -export function postProfile(request: any, body: any, token: string, statusCode: number = HTTP_STATUS.OK): Promise { +export function postProfile( + request: any, + body: any, + token: string, + statusCode: number = HTTP_STATUS.OK +): Promise { // $FlowFixMe return new Promise((resolve) => { request @@ -141,7 +176,13 @@ export function postProfile(request: any, body: any, token: string, statusCode: }); } -export async function fetchPackageByVersionAndTag(app, encodedPkgName, pkgName, version, tag = 'latest') { +export async function fetchPackageByVersionAndTag( + app, + encodedPkgName, + pkgName, + version, + tag = 'latest' +) { // we retrieve the package to verify const [err, resp] = await getPackage(request(app), '', encodedPkgName); @@ -158,7 +199,12 @@ export async function isExistPackage(app, packageName) { } export async function verifyPackageVersionDoesExist(app, packageName, version, token?: string) { - const [, res] = await getPackage(request(app), token as string, encodeScopedUri(packageName), HTTP_STATUS.OK); + const [, res] = await getPackage( + request(app), + token as string, + encodeScopedUri(packageName), + HTTP_STATUS.OK + ); const { versions } = res.body; const versionsKeys = Object.keys(versions); diff --git a/packages/verdaccio/test/unit/__helper/utils.ts b/packages/verdaccio/test/unit/__helper/utils.ts index f8d4b17b0..7270a8375 100644 --- a/packages/verdaccio/test/unit/__helper/utils.ts +++ b/packages/verdaccio/test/unit/__helper/utils.ts @@ -35,7 +35,8 @@ export function generateVersion(pkgName, version) { name: 'foo', }, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`, }, diff --git a/packages/verdaccio/test/unit/partials/forbidden-place.js b/packages/verdaccio/test/unit/partials/forbidden-place.js index ee87990dd..23ec4c1ae 100644 --- a/packages/verdaccio/test/unit/partials/forbidden-place.js +++ b/packages/verdaccio/test/unit/partials/forbidden-place.js @@ -30,7 +30,8 @@ const json = { _nodeVersion: '8.7.0', _npmUser: {}, dist: { - integrity: 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', + integrity: + 'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==', shasum: '2c03764f651a9f016ca0b7620421457b619151b9', tarball: 'http://localhost:5555/forbidden-place/-/forbidden-place-1.0.6.tgz', }, diff --git a/packages/verdaccio/test/unit/partials/storage/verdaccio.db.json b/packages/verdaccio/test/unit/partials/storage/verdaccio.db.json index 98193af08..d51675406 100644 --- a/packages/verdaccio/test/unit/partials/storage/verdaccio.db.json +++ b/packages/verdaccio/test/unit/partials/storage/verdaccio.db.json @@ -1 +1,4 @@ -{ "list": ["@verdaccio/test"], "secret": "48cd053de97d4ef34aea4f1efb902334442bea1e735df5fdc9424c986a281b3d" } +{ + "list": ["@verdaccio/test"], + "secret": "48cd053de97d4ef34aea4f1efb902334442bea1e735df5fdc9424c986a281b3d" +} diff --git a/packages/web/package.json b/packages/web/package.json index b69e81464..d319974b2 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -20,7 +20,6 @@ "lodash": "^4.17.20" }, "devDependencies": { - "@verdaccio/dev-types": "workspace:5.0.0-alpha.0", "@verdaccio/types": "workspace:*" }, "scripts": { diff --git a/packages/web/src/endpoint/package.ts b/packages/web/src/endpoint/package.ts index 0e5f894dd..8b1d6f0dc 100644 --- a/packages/web/src/endpoint/package.ts +++ b/packages/web/src/endpoint/package.ts @@ -12,19 +12,30 @@ import { import { allow } from '@verdaccio/middleware'; import { DIST_TAGS, HEADER_TYPE, HEADERS, HTTP_STATUS } from '@verdaccio/dev-commons'; import { logger } from '@verdaccio/logger'; -import { Router } from 'express'; -import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler, $SidebarPackage } from '@verdaccio/dev-types'; -import { Config, Package } from '@verdaccio/types'; +import { NextFunction, Request, Response, Router } from 'express'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; +import { Config, Logger, Package } from '@verdaccio/types'; import { addGravatarSupport } from '../web-utils'; import { generateGravatarUrl } from '../user'; +export type $SidebarPackage = Package & { latest: any }; +export type $RequestExtend = Request & { remote_user?: any; log: Logger }; +export type $ResponseExtend = Response & { cookies?: any }; +export type $NextFunctionVer = NextFunction & any; + const getOrder = (order = 'asc') => { return order === 'asc'; }; export type PackcageExt = Package & { author: any; dist?: { tarball: string } }; -function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, config: Config): void { +function addPackageWebApi( + route: Router, + storage: IStorageHandler, + auth: IAuth, + config: Config +): void { const can = allow(auth); const checkAllow = (name, remoteUser): Promise => @@ -42,7 +53,11 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, }); // Get list of all visible package - route.get('/packages', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.get('/packages', function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { storage.getLocalDatabase(async function (err, packages): Promise { if (err) { throw err; @@ -57,15 +72,26 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, try { if (await checkAllow(pkg.name, req.remote_user)) { if (config.web) { - pkgCopy.author.avatar = generateGravatarUrl(pkgCopy.author.email, config.web.gravatar); + 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); + 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}'); + logger.logger.error( + { name: pkg.name, error: err }, + 'permission process for @{name} has failed: @{error}' + ); throw err; } } @@ -82,8 +108,14 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, }); // Get package readme - route.get('/package/readme/(@:scope/)?:package/:version?', can('access'), function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { - const packageName = req.params.scope ? addScope(req.params.scope, req.params.package) : req.params.package; + route.get('/package/readme/(@:scope/)?:package/:version?', can('access'), function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { + const packageName = req.params.scope + ? addScope(req.params.scope, req.params.package) + : req.params.package; storage.getPackage({ name: packageName, @@ -100,8 +132,14 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, }); }); - 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; + 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, @@ -112,7 +150,11 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth, if (_.isNil(err)) { const { v } = req.query; let sideBarInfo: any = _.clone(info); - sideBarInfo.versions = convertDistRemoteToLocalTarballUrls(info, req, config.url_prefix).versions; + sideBarInfo.versions = convertDistRemoteToLocalTarballUrls( + info, + req, + config.url_prefix + ).versions; if (isVersionValid(info, v)) { // @ts-ignore sideBarInfo.latest = sideBarInfo.versions[v]; diff --git a/packages/web/src/endpoint/search.ts b/packages/web/src/endpoint/search.ts index 51fe566d9..fdd1d3253 100644 --- a/packages/web/src/endpoint/search.ts +++ b/packages/web/src/endpoint/search.ts @@ -1,12 +1,18 @@ import { SearchInstance } from '@verdaccio/store'; import { DIST_TAGS } from '@verdaccio/dev-commons'; import { Router } from 'express'; -import { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler } from '@verdaccio/dev-types'; import { Package } from '@verdaccio/types'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; +import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from './package'; function addSearchWebApi(route: Router, storage: IStorageHandler, auth: IAuth): void { // Search package - route.get('/search/:anything', function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void { + route.get('/search/:anything', function ( + req: $RequestExtend, + res: $ResponseExtend, + next: $NextFunctionVer + ): void { const results: any = SearchInstance.query(req.params.anything); // FUTURE: figure out here the correct type const packages: any[] = []; @@ -17,7 +23,10 @@ function addSearchWebApi(route: Router, storage: IStorageHandler, auth: IAuth): uplinksLook: false, callback: (err, entry: Package): void => { if (!err && entry) { - auth.allow_access({ packageName: entry.name }, req.remote_user, function (err, allowed): void { + auth.allow_access({ packageName: entry.name }, req.remote_user, function ( + err, + allowed + ): void { if (err || !allowed) { return; } diff --git a/packages/web/src/endpoint/user.ts b/packages/web/src/endpoint/user.ts index fcaf301ce..ac14e3c62 100644 --- a/packages/web/src/endpoint/user.ts +++ b/packages/web/src/endpoint/user.ts @@ -4,9 +4,10 @@ import { Router, Response, Request } from 'express'; import { Config, RemoteUser, JWTSignOptions } from '@verdaccio/types'; import { API_ERROR, APP_ERROR, HTTP_STATUS } from '@verdaccio/dev-commons'; -import { IAuth, $NextFunctionVer } from '@verdaccio/dev-types'; +import { IAuth } from '@verdaccio/auth'; import { validatePassword, ErrorCode } from '@verdaccio/utils'; import { getSecurity } from '@verdaccio/auth'; +import { $NextFunctionVer } from './package'; function addUserAuthApi(route: Router, auth: IAuth, config: Config): void { route.post('/login', function (req: Request, res: Response, next: $NextFunctionVer): void { @@ -32,7 +33,11 @@ function addUserAuthApi(route: Router, auth: IAuth, config: Config): void { ); }); - route.put('/reset_password', function (req: Request, res: Response, next: $NextFunctionVer): void { + route.put('/reset_password', function ( + req: Request, + res: Response, + next: $NextFunctionVer + ): void { if (_.isNil(req.remote_user.name)) { res.status(HTTP_STATUS.UNAUTHORIZED); return next({ diff --git a/packages/web/src/web-api.ts b/packages/web/src/web-api.ts index 38a60b4e4..9d6998676 100644 --- a/packages/web/src/web-api.ts +++ b/packages/web/src/web-api.ts @@ -4,7 +4,8 @@ import bodyParser from 'body-parser'; import { SearchInstance } from '@verdaccio/store'; import { match, validateName, validatePackage, setSecurityWebHeaders } from '@verdaccio/middleware'; import { Config } from '@verdaccio/types'; -import { IAuth, IStorageHandler } from '@verdaccio/dev-types'; +import { IAuth } from '@verdaccio/auth'; +import { IStorageHandler } from '@verdaccio/store'; import addSearchWebApi from './endpoint/search'; import addPackageWebApi from './endpoint/package'; import addUserAuthApi from './endpoint/user'; diff --git a/packages/web/src/web-utils.ts b/packages/web/src/web-utils.ts index 37f8d8fe7..469cb588d 100644 --- a/packages/web/src/web-utils.ts +++ b/packages/web/src/web-utils.ts @@ -2,14 +2,17 @@ import _ from 'lodash'; import { isObject } from '@verdaccio/utils'; import { Package, Author } from '@verdaccio/types'; import { normalizeContributors } from '@verdaccio/store'; -import { AuthorAvatar } from '@verdaccio/dev-types'; + +export type AuthorAvatar = Author & { avatar?: string }; import { generateGravatarUrl, GENERIC_AVATAR } from './user'; export function addGravatarSupport(pkgInfo: Package, online = true): AuthorAvatar { const pkgInfoCopy = { ...pkgInfo } as any; const author: any = _.get(pkgInfo, 'latest.author', null) as any; - const contributors: AuthorAvatar[] = normalizeContributors(_.get(pkgInfo, 'latest.contributors', [])); + const contributors: AuthorAvatar[] = normalizeContributors( + _.get(pkgInfo, 'latest.contributors', []) + ); const maintainers = _.get(pkgInfo, 'latest.maintainers', []); // for author. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4c523672..0c132da6e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -166,7 +166,7 @@ importers: selfsigned: 1.10.7 standard-version: 8.0.0 supertest: 4.0.2 - typescript: '>=3.3.1 <3.10.0' + typescript: ^3.9.7 verdaccio: latest verdaccio-audit: latest verdaccio-auth-memory: latest @@ -190,7 +190,6 @@ importers: semver: 7.3.2 devDependencies: '@verdaccio/config': 'link:../config' - '@verdaccio/dev-types': 'link:../types' '@verdaccio/server': 'link:../server' '@verdaccio/types': 'link:../core/types' body-parser: 1.19.0 @@ -200,7 +199,6 @@ importers: '@verdaccio/commons-api': 'workspace:*' '@verdaccio/config': 'workspace:5.0.0-alpha.0' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/hooks': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/middleware': 'workspace:5.0.0-alpha.0' @@ -228,14 +226,12 @@ importers: lodash: 4.17.15 devDependencies: '@verdaccio/config': 'link:../config' - '@verdaccio/dev-types': 'link:../types' '@verdaccio/mock': 'link:../mock' '@verdaccio/types': 'link:../core/types' specifiers: '@verdaccio/commons-api': 'workspace:*' '@verdaccio/config': 'workspace:5.0.0-alpha.0' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/loaders': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/mock': 'workspace:5.0.0-alpha.0' @@ -277,11 +273,8 @@ importers: '@verdaccio/utils': 'link:../utils' lodash: 4.17.20 mkdirp: 0.5.5 - devDependencies: - '@verdaccio/dev-types': 'link:../types' specifiers: '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/utils': 'workspace:5.0.0-alpha.0' lodash: ^4.17.20 @@ -380,7 +373,6 @@ importers: '@verdaccio/auth': 'link:../auth' '@verdaccio/config': 'link:../config' '@verdaccio/dev-commons': 'link:../commons' - '@verdaccio/dev-types': 'link:../types' '@verdaccio/types': 'link:../core/types' '@verdaccio/utils': 'link:../utils' specifiers: @@ -388,7 +380,6 @@ importers: '@verdaccio/commons-api': 'workspace:*' '@verdaccio/config': 'workspace:5.0.0-alpha.0' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/types': 'workspace:*' '@verdaccio/utils': 'workspace:5.0.0-alpha.0' @@ -404,14 +395,12 @@ importers: devDependencies: '@verdaccio/commons-api': 'link:../core/commons-api' '@verdaccio/config': 'link:../config' - '@verdaccio/dev-types': 'link:../types' '@verdaccio/mock': 'link:../mock' '@verdaccio/types': 'link:../core/types' specifiers: '@verdaccio/commons-api': 'workspace:*' '@verdaccio/config': 'workspace:5.0.0-alpha.0' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/mock': 'workspace:5.0.0-alpha.0' '@verdaccio/types': 'workspace:*' @@ -461,17 +450,16 @@ importers: pretty-ms: 5.0.0 packages/middleware: dependencies: + '@verdaccio/auth': 'link:../auth' '@verdaccio/commons-api': 'link:../core/commons-api' '@verdaccio/dev-commons': 'link:../commons' '@verdaccio/logger': 'link:../logger' '@verdaccio/utils': 'link:../utils' lodash: 4.17.15 - devDependencies: - '@verdaccio/dev-types': 'link:../types' specifiers: + '@verdaccio/auth': 'workspace:5.0.0-alpha.0' '@verdaccio/commons-api': 'workspace:*' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/utils': 'workspace:5.0.0-alpha.0' lodash: 4.17.15 @@ -485,11 +473,9 @@ importers: supertest: 4.0.2 verdaccio: 4.8.1 devDependencies: - '@verdaccio/dev-types': 'link:../types' '@verdaccio/types': 'link:../core/types' specifiers: '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/types': 'workspace:*' '@verdaccio/utils': 'workspace:5.0.0-alpha.0' fs-extra: ^8.1.0 @@ -528,11 +514,9 @@ importers: lodash: 4.17.20 request: 2.87.0 devDependencies: - '@verdaccio/dev-types': 'link:../types' '@verdaccio/types': 'link:../core/types' specifiers: '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/local-storage': 'workspace:*' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/streams': 'workspace:*' @@ -559,7 +543,6 @@ importers: lodash: 4.17.15 devDependencies: '@verdaccio/commons-api': 'link:../core/commons-api' - '@verdaccio/dev-types': 'link:../types' '@verdaccio/mock': 'link:../mock' '@verdaccio/proxy': 'link:../proxy' http-errors: 1.7.3 @@ -571,7 +554,6 @@ importers: '@verdaccio/commons-api': 'workspace:*' '@verdaccio/config': 'workspace:5.0.0-alpha.0' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/loaders': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/middleware': 'workspace:5.0.0-alpha.0' @@ -604,14 +586,12 @@ importers: semver: 7.1.2 devDependencies: '@verdaccio/config': 'link:../config' - '@verdaccio/dev-types': 'link:../types' '@verdaccio/mock': 'link:../mock' '@verdaccio/types': 'link:../core/types' specifiers: '@verdaccio/commons-api': 'workspace:*' '@verdaccio/config': 'workspace:5.0.0-alpha.0' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/loaders': 'workspace:5.0.0-alpha.0' '@verdaccio/local-storage': 'workspace:*' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' @@ -641,14 +621,12 @@ importers: semver: 7.3.2 devDependencies: '@types/minimatch': 3.0.3 - '@verdaccio/dev-types': 'link:../types' '@verdaccio/logger': 'link:../logger' lodash: 4.17.20 specifiers: '@types/minimatch': 3.0.3 '@verdaccio/commons-api': 'workspace:*' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/readme': 'workspace:*' js-yaml: 3.13.1 @@ -693,12 +671,10 @@ importers: express: 4.17.1 lodash: 4.17.20 devDependencies: - '@verdaccio/dev-types': 'link:../types' '@verdaccio/types': 'link:../core/types' specifiers: '@verdaccio/auth': 'workspace:5.0.0-alpha.0' '@verdaccio/dev-commons': 'workspace:5.0.0-alpha.0' - '@verdaccio/dev-types': 'workspace:5.0.0-alpha.0' '@verdaccio/loaders': 'workspace:5.0.0-alpha.0' '@verdaccio/logger': 'workspace:5.0.0-alpha.0' '@verdaccio/middleware': 'workspace:5.0.0-alpha.0' diff --git a/test/e2e-cli/setup/setup.ts b/test/e2e-cli/setup/setup.ts index 64ad8a518..3b9dabaeb 100644 --- a/test/e2e-cli/setup/setup.ts +++ b/test/e2e-cli/setup/setup.ts @@ -10,7 +10,10 @@ module.exports = async () => { const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'verdaccio-cli-e2e-')); __global.addItem('dir-root', tempRoot); console.log(yellow(`Add temp root folder: ${tempRoot}`)); - fs.copyFileSync(path.join(__dirname, '../config/_bootstrap_verdaccio.yaml'), path.join(tempRoot, 'verdaccio.yaml')); + fs.copyFileSync( + path.join(__dirname, '../config/_bootstrap_verdaccio.yaml'), + path.join(tempRoot, 'verdaccio.yaml') + ); // @ts-ignore global.__namespace = __global; console.log(`current directory: ${process.cwd()}`); diff --git a/test/e2e-cli/test/__partials/npm_commands.ts b/test/e2e-cli/test/__partials/npm_commands.ts index 964ee6640..b821777d1 100644 --- a/test/e2e-cli/test/__partials/npm_commands.ts +++ b/test/e2e-cli/test/__partials/npm_commands.ts @@ -1,5 +1,13 @@ import { silentNpm } from '../../utils/process'; export function installVerdaccio(verdaccioInstall) { - return silentNpm('install', '--prefix', verdaccioInstall, 'verdaccio', '--registry', 'http://localhost:4873', '--no-package-lock'); + return silentNpm( + 'install', + '--prefix', + verdaccioInstall, + 'verdaccio', + '--registry', + 'http://localhost:4873', + '--no-package-lock' + ); } diff --git a/test/e2e-cli/test/core/info.spec.ts b/test/e2e-cli/test/core/info.spec.ts index 86854dd5d..910a8520d 100644 --- a/test/e2e-cli/test/core/info.spec.ts +++ b/test/e2e-cli/test/core/info.spec.ts @@ -17,7 +17,12 @@ describe('verdaccio info', () => { const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { paths: [verdaccioInstall], }); - const hasMatch = await runVerdaccio(pathVerdaccioModule, verdaccioInstall, ['--info'], /Environment/); + const hasMatch = await runVerdaccio( + pathVerdaccioModule, + verdaccioInstall, + ['--info'], + /Environment/ + ); expect(hasMatch.ok).toBeTruthy(); }); diff --git a/test/e2e-cli/test/core/listen.spec.ts b/test/e2e-cli/test/core/listen.spec.ts index e8c9e5dc1..eecd2ab51 100644 --- a/test/e2e-cli/test/core/listen.spec.ts +++ b/test/e2e-cli/test/core/listen.spec.ts @@ -24,7 +24,10 @@ describe('npm install', () => { paths: [verdaccioInstall], }); - registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { cwd: verdaccioInstall, silent: true }); + registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { + cwd: verdaccioInstall, + silent: true, + }); const body = await callRegistry(`http://localhost:${port}/verdaccio`); const parsedBody = JSON.parse(body); diff --git a/test/e2e-cli/test/install/install.spec.ts b/test/e2e-cli/test/install/install.spec.ts index cefd0008d..577bce520 100644 --- a/test/e2e-cli/test/install/install.spec.ts +++ b/test/e2e-cli/test/install/install.spec.ts @@ -25,23 +25,37 @@ describe('npm install', () => { const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { paths: [verdaccioInstall], }); - registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { cwd: verdaccioInstall, silent: true }); + registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { + cwd: verdaccioInstall, + silent: true, + }); }); test('should match on npm info verdaccio', async () => { // FIXME: not the best match, looking for a better way to match the terminal output - const output = await execAndWaitForOutputToMatch('npm', ['info', 'verdaccio', '--registry'], /A lightweight private npm proxy registry/); + const output = await execAndWaitForOutputToMatch( + 'npm', + ['info', 'verdaccio', '--registry'], + /A lightweight private npm proxy registry/ + ); expect(output.ok).toBeTruthy(); }); test('should install jquery', async () => { const testCwd = path.join(tempRootFolder, '_jquery_'); - await execAndWaitForOutputToMatch('npm', ['install', '--prefix', testCwd, 'jquery', '--registry', `http://localhost:${port}`], /''/, { - cwd: verdaccioInstall, - }); + await execAndWaitForOutputToMatch( + 'npm', + ['install', '--prefix', testCwd, 'jquery', '--registry', `http://localhost:${port}`], + /''/, + { + cwd: verdaccioInstall, + } + ); - const exist = await expectFileToExist(path.join(testCwd, 'node_modules', 'jquery', 'package.json')); + const exist = await expectFileToExist( + path.join(testCwd, 'node_modules', 'jquery', 'package.json') + ); expect(exist).toBeTruthy(); }); diff --git a/test/e2e-cli/utils/process.ts b/test/e2e-cli/utils/process.ts index edbf228b9..e8bca4187 100644 --- a/test/e2e-cli/utils/process.ts +++ b/test/e2e-cli/utils/process.ts @@ -76,7 +76,12 @@ export async function _exec(options, cmd, args) { }); } -export function execAndWaitForOutputToMatch(cmd: string, args: string[], match: RegExp, spawnOptions: SpawnOptions = {}): any { +export function execAndWaitForOutputToMatch( + cmd: string, + args: string[], + match: RegExp, + spawnOptions: SpawnOptions = {} +): any { return _exec({ waitForMatch: match, ...spawnOptions, silence: true }, cmd, args); } diff --git a/tsconfig.base.json b/tsconfig.base.json index e7d00b9d2..41c3d8146 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -11,5 +11,14 @@ "allowSyntheticDefaultImports": true, "esModuleInterop": true }, - "exclude": ["**/build", "node_modules", "**/node_modules", "**/coverage", "**/*.spec.ts", "**/test", "**/__tests__", "**/*.test.ts"] + "exclude": [ + "**/build", + "node_modules", + "**/node_modules", + "**/coverage", + "**/*.spec.ts", + "**/test", + "**/__tests__", + "**/*.test.ts" + ] } diff --git a/website/config/sidebar.json b/website/config/sidebar.json index 1f574e0b1..044758019 100644 --- a/website/config/sidebar.json +++ b/website/config/sidebar.json @@ -18,7 +18,15 @@ "ids": ["articles", "talks"] } ], - "Features": ["configuration", "uplinks", "packages", "authentification", "notifications", "logger", "webui"], + "Features": [ + "configuration", + "uplinks", + "packages", + "authentification", + "notifications", + "logger", + "webui" + ], "Server": ["server-configuration", "reverse-proxy", "ssl", "windows", "iss-server"], "Development": [ "plugins", diff --git a/website/docs/logger.md b/website/docs/logger.md index a59ccf7bf..8ed527e76 100644 --- a/website/docs/logger.md +++ b/website/docs/logger.md @@ -14,7 +14,13 @@ logs: # file output - { type: file, path: verdaccio.log, level: info } # Rotating log stream. Options are passed directly to bunyan. See: https://github.com/trentm/node-bunyan#stream-type-rotating-file - - { type: rotating-file, format: json, path: /path/to/log.jsonl, level: http, options: { period: 1d } } + - { + type: rotating-file, + format: json, + path: /path/to/log.jsonl, + level: http, + options: { period: 1d }, + } ``` Use `SIGUSR2` to notify the application, the log-file was rotated and it needs to reopen it. diff --git a/website/docs/node-api.md b/website/docs/node-api.md index e0ba7634b..48fe75d0a 100644 --- a/website/docs/node-api.md +++ b/website/docs/node-api.md @@ -14,11 +14,18 @@ Verdaccio can be invoked programmatically. The node API was introduced after ver ```js import startServer from 'verdaccio'; -startServer(configJsonFormat, 6000, store, '1.0.0', 'verdaccio', (webServer, addrs, pkgName, pkgVersion) => { - webServer.listen(addr.port || addr.path, addr.host, () => { - console.log('verdaccio running'); - }); -}); +startServer( + configJsonFormat, + 6000, + store, + '1.0.0', + 'verdaccio', + (webServer, addrs, pkgName, pkgVersion) => { + webServer.listen(addr.port || addr.path, addr.host, () => { + console.log('verdaccio running'); + }); + } +); ``` ## Other implementations diff --git a/website/docs/plugin-auth.md b/website/docs/plugin-auth.md index dd8451e48..c88156e65 100644 --- a/website/docs/plugin-auth.md +++ b/website/docs/plugin-auth.md @@ -51,7 +51,11 @@ interface IPluginAuth extends IPlugin { changePassword?(user: string, password: string, newPassword: string, cb: AuthCallback): void; allow_publish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void; allow_access?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void; - allow_unpublish?(user: RemoteUser, pkg: AllowAccess & PackageAccess, cb: AuthAccessCallback): void; + allow_unpublish?( + user: RemoteUser, + pkg: AllowAccess & PackageAccess, + cb: AuthAccessCallback + ): void; apiJWTmiddleware?(helpers: any): Function; } ``` diff --git a/website/docs/plugin-storage.md b/website/docs/plugin-storage.md index 9bb7066a8..5e5f2d95b 100644 --- a/website/docs/plugin-storage.md +++ b/website/docs/plugin-storage.md @@ -25,7 +25,11 @@ interface IPluginStorage extends IPlugin, ITokenActions { getSecret(): Promise; setSecret(secret: string): Promise; getPackageStorage(packageInfo: string): IPackageStorage; - search(onPackage: onSearchPackage, onEnd: onEndSearchPackage, validateName: onValidatePackage): void; + search( + onPackage: onSearchPackage, + onEnd: onEndSearchPackage, + validateName: onValidatePackage + ): void; } ``` diff --git a/website/src/components/AppDrawer/AppDrawer.tsx b/website/src/components/AppDrawer/AppDrawer.tsx index 9e87854fb..5a7897f89 100644 --- a/website/src/components/AppDrawer/AppDrawer.tsx +++ b/website/src/components/AppDrawer/AppDrawer.tsx @@ -18,10 +18,24 @@ export type Props = { const DrawerSideBar = () => { const { currentPage, idTitleMap, language, sideBarConfiguration } = usePageContext(); - return ; + return ( + + ); }; -const AppDrawer: FunctionComponent = ({ className, isPermanent, onClose, onOpen, open, classes }) => { +const AppDrawer: FunctionComponent = ({ + className, + isPermanent, + onClose, + onOpen, + open, + classes, +}) => { return (