mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-11-08 23:25:51 +01:00
refactor: test api refactor (#1826)
* test: add test for whoami * Update middleware.ts * test for user api * more test for user api * remove repeated code * refactor * Update index.spec.ts * add package test refactor others * chore: upgrade deps * chore: add test for package * chore: update test * update lock file * Update ci.yml * Update ci.yml * Update package.spec.ts * chore: update ci settings * chore: update deps * chore: update test
This commit is contained in:
parent
d3f78e5b34
commit
a7ba76423e
@ -13,6 +13,9 @@ Dockerfile
|
||||
*.html
|
||||
*.scss
|
||||
*.png
|
||||
*.json
|
||||
*.name
|
||||
*.tgz
|
||||
*.jpg
|
||||
*.sh
|
||||
**/partials/**
|
||||
|
99
.eslintrc
99
.eslintrc
@ -1,102 +1,21 @@
|
||||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"google",
|
||||
"plugin:react/recommended",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:jsx-a11y/recommended",
|
||||
"prettier"
|
||||
"@verdaccio"
|
||||
],
|
||||
"plugins": ["import", "jest", "jsx-a11y", "react-hooks"],
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"jest": true
|
||||
},
|
||||
"globals": {
|
||||
"__APP_VERSION__": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"allowImportExportEverywhere": true,
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 11,
|
||||
"ecmaFeatures": {
|
||||
"impliedStrict": true,
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"node": {
|
||||
"extensions": [".js", ".jsx", ".ts", ".tsx"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"rules": {
|
||||
"curly": ["error", "all"],
|
||||
"react/prop-types": 0,
|
||||
"jest/no-export": 0,
|
||||
"jest/no-test-callback": 0,
|
||||
"jest/expect-expect": 0,
|
||||
"jest/no-try-expect": 0,
|
||||
"jest/no-done-callback": "off",
|
||||
"jest/no-conditional-expect": "off",
|
||||
"keyword-spacing": "off",
|
||||
"no-tabs": "off",
|
||||
"no-useless-escape": "off",
|
||||
"padded-blocks": "off",
|
||||
"require-jsdoc": "off",
|
||||
"valid-jsdoc": "off",
|
||||
"import/order": ["error"],
|
||||
"eol-last": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
|
||||
"no-trailing-spaces": "error",
|
||||
"camelcase": "off",
|
||||
"guard-for-in": "error",
|
||||
"new-cap": "error",
|
||||
"max-len": ["error", 180],
|
||||
"no-console": ["error", { "allow": ["warn"] }],
|
||||
"no-constant-condition": "error",
|
||||
"no-debugger": "error",
|
||||
"no-empty": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-invalid-this": "error",
|
||||
"no-new-require": "error",
|
||||
"no-undef": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-var": "error",
|
||||
"one-var": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"handle-callback-err": 0,
|
||||
"prefer-const": 0,
|
||||
"@typescript-eslint/camelcase": 0,
|
||||
"@typescript-eslint/ban-ts-ignore": 0,
|
||||
"@typescript-eslint/no-var-requires": 0,
|
||||
"@typescript-eslint/ban-ts-ignore": 0,
|
||||
"@typescript-eslint/no-inferrable-types": 0,
|
||||
"@typescript-eslint/no-empty-function": 0,
|
||||
"@typescript-eslint/no-this-alias": 0,
|
||||
"@typescript-eslint/no-this-alias": ["warn"],
|
||||
"@typescript-eslint/no-use-before-define": 0,
|
||||
"@typescript-eslint/array-type": ["error"],
|
||||
"@typescript-eslint/array-type": ["warn"],
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
"@typescript-eslint/indent": 0,
|
||||
"@typescript-eslint/ban-ts-comment": 0,
|
||||
"@typescript-eslint/ban-types": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
||||
|
||||
// rules to fix
|
||||
"no-unused-vars": ["warn", { "vars": "all", "args": "none" }],
|
||||
"jest/no-identical-title": ["warn"],
|
||||
"prefer-promise-reject-errors": ["warn"],
|
||||
"jest/no-disabled-tests": ["warn"],
|
||||
"jest/no-commented-out-tests": ["warn"],
|
||||
"@typescript-eslint/prefer-optional-chain": ["warn"],
|
||||
"@typescript-eslint/explicit-member-accessibility": ["warn"],
|
||||
"@typescript-eslint/no-unused-vars": ["warn"]
|
||||
"@typescript-eslint/interface-name-prefix": 0,
|
||||
"import/order": 0,
|
||||
"handle-callback-err": 1,
|
||||
"prefer-const": 1,
|
||||
"prefer-promise-reject-errors": 1
|
||||
}
|
||||
}
|
||||
|
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -1,6 +1,16 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/ci.yml
|
||||
- 'packages/**'
|
||||
- 'jest/**'
|
||||
- 'package.json'
|
||||
- 'lerna.json'
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
|
@ -1,12 +1,6 @@
|
||||
name: Docker & Publish Pre-check
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'packages/**'
|
||||
- 'docker-bin/**'
|
||||
- 'package.json'
|
||||
- 'lerna.json'
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/docker-publish-pre-check.yml
|
||||
|
2
.github/workflows/docker-publish.yml
vendored
2
.github/workflows/docker-publish.yml
vendored
@ -2,6 +2,8 @@ name: Docker publish to GitHub registry
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- .github/workflows/docker-publish.yml
|
||||
- 'packages/**'
|
||||
|
23
debug/DEBUGGING.md
Normal file
23
debug/DEBUGGING.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Debuging Documentation
|
||||
|
||||
|
||||
## Debugging tests
|
||||
|
||||
|
||||
|
||||
### Running a single test
|
||||
|
||||
```bash
|
||||
yarn test test/integration/package.spec.ts --runInBand
|
||||
```
|
||||
|
||||
Using `--runInBand` allows you to see the `console.log` prints, without that `jest` hidde them.
|
||||
|
||||
#### Display additional information
|
||||
|
||||
You can take advance of `debug` module used by many dependencies, eg:
|
||||
|
||||
* `supertest`: `DEBUG=superagent yarn test test/integration/package.spec.ts --runInBand`
|
||||
* `express`: `DEBUG=express:* yarn test test/integration/package.spec.ts --runInBand`
|
||||
* `nock`: `DEBUG=nock yarn test test/integration/package.spec.ts --runInBand`
|
||||
* All of if: `DEBUG=* yarn test test/integration/package.spec.ts --runInBand`
|
39
package.json
39
package.json
@ -21,18 +21,19 @@
|
||||
"@commitlint/cli": "8.3.5",
|
||||
"@commitlint/config-conventional": "8.2.0",
|
||||
"@octokit/rest": "17.0.0",
|
||||
"@types/async": "3.0.3",
|
||||
"@types/express": "4.17.1",
|
||||
"@types/async": "3.2.3",
|
||||
"@types/express": "4.17.6",
|
||||
"@types/http-errors": "1.6.3",
|
||||
"@types/jest": "25.2.3",
|
||||
"@types/lodash": "4.14.151",
|
||||
"@types/jest": "26.0.1",
|
||||
"@types/lodash": "4.14.156",
|
||||
"@types/mime": "2.0.2",
|
||||
"@types/minimatch": "3.0.3",
|
||||
"@types/node": "12.12.21",
|
||||
"@types/node": "14.0.14",
|
||||
"@types/request": "2.48.3",
|
||||
"@types/semver": "7.2.0",
|
||||
"@verdaccio/babel-preset": "9.4.0",
|
||||
"@verdaccio/eslint-config": "9.0.0",
|
||||
"@types/supertest": "2.0.9",
|
||||
"@verdaccio/babel-preset": "9.6.1",
|
||||
"@verdaccio/eslint-config": "9.3.2",
|
||||
"@verdaccio/types": "9.5.0",
|
||||
"codecov": "3.6.1",
|
||||
"cross-env": "7.0.2",
|
||||
@ -42,22 +43,22 @@
|
||||
"get-stdin": "7.0.0",
|
||||
"husky": "2.7.0",
|
||||
"in-publish": "2.0.0",
|
||||
"jest": "26.0.1",
|
||||
"jest-environment-node": "26.0.1",
|
||||
"jest-junit": "10.0.0",
|
||||
"jest": "26.1.0",
|
||||
"jest-environment-node": "26.1.0",
|
||||
"jest-junit": "11.0.1",
|
||||
"kleur": "3.0.3",
|
||||
"lerna": "3.21.0",
|
||||
"lerna": "3.22.1",
|
||||
"lint-staged": "8.2.1",
|
||||
"nock": "11.7.2",
|
||||
"nock": "12.0.3",
|
||||
"prettier": "1.19.1",
|
||||
"rimraf": "3.0.0",
|
||||
"rimraf": "3.0.2",
|
||||
"selfsigned": "1.10.7",
|
||||
"standard-version": "7.0.1",
|
||||
"standard-version": "8.0.0",
|
||||
"supertest": "4.0.2",
|
||||
"typescript": "3.9.2",
|
||||
"verdaccio": "4.6.2",
|
||||
"verdaccio-auth-memory": "9.3.0",
|
||||
"verdaccio-memory": "9.3.0"
|
||||
"typescript": "3.9.5",
|
||||
"verdaccio": "4.7.1",
|
||||
"verdaccio-auth-memory": "9.7.0",
|
||||
"verdaccio-memory": "9.7.0"
|
||||
},
|
||||
"scripts": {
|
||||
"bootstrap": "lerna bootstrap",
|
||||
@ -73,7 +74,7 @@
|
||||
"release:prerelease": "lerna version --conventional-commits --conventional-prerelease --preid next --registry http://localhost:4873",
|
||||
"release:publish": "lerna publish from-git",
|
||||
"release:publish-prerelease": "lerna publish from-git --pre-dist-tag next",
|
||||
"lint": "eslint \"packages/**/@(src|tests)/**\"",
|
||||
"lint": "eslint \"packages/**/@(src|tests|test)/**\"",
|
||||
"test": "lerna run test --concurrency 1",
|
||||
"test:e2e:cli": "cross-env NODE_ENV=test jest --config ./test/e2e-cli/jest.config.e2e.cli.js --passWithNoTests",
|
||||
"website:lint": "cd website && yarn lint",
|
||||
|
19
packages/api/__mocks__/@verdaccio/logger/index.js
Normal file
19
packages/api/__mocks__/@verdaccio/logger/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
const setup = jest.fn();
|
||||
const logger = {
|
||||
child: jest.fn(() => ({
|
||||
debug: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
info: jest.fn(),
|
||||
error: jest.fn(),
|
||||
fatal: jest.fn(),
|
||||
})),
|
||||
debug: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
info: jest.fn(),
|
||||
error: jest.fn(),
|
||||
fatal: jest.fn(),
|
||||
};
|
||||
|
||||
export { setup, logger }
|
@ -24,11 +24,12 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@verdaccio/auth": "5.0.0-alpha.0",
|
||||
"@verdaccio/commons-api": "9.4.0",
|
||||
"@verdaccio/commons-api": "9.6.1",
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"@verdaccio/hooks": "5.0.0-alpha.0",
|
||||
"@verdaccio/logger": "5.0.0-alpha.0",
|
||||
"@verdaccio/middleware": "5.0.0-alpha.0",
|
||||
"@verdaccio/store": "5.0.0-alpha.0",
|
||||
"@verdaccio/utils": "5.0.0-alpha.0",
|
||||
"body-parser": "1.19.0",
|
||||
"cookies": "0.8.0",
|
||||
@ -38,7 +39,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@verdaccio/dev-types": "5.0.0-alpha.0",
|
||||
"@verdaccio/types": "9.3.0"
|
||||
"@verdaccio/types": "9.5.0",
|
||||
"express": "4.17.1"
|
||||
},
|
||||
"gitHead": "7c246ede52ff717707fcae66dd63fc4abd536982"
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ export default function(config: Config, auth: IAuth, storage: IStorageHandler):
|
||||
app.param('_rev', match(/^-rev$/));
|
||||
app.param('org_couchdb_user', match(/^org\.couchdb\.user:/));
|
||||
app.param('anything', match(/.*/));
|
||||
|
||||
app.use(auth.apiJWTmiddleware());
|
||||
app.use(bodyParser.json({ strict: false, limit: config.max_body_size || '10mb' }));
|
||||
// @ts-ignore
|
||||
|
@ -15,7 +15,7 @@ const downloadStream = (packageName: string, filename: string, storage: any, req
|
||||
});
|
||||
|
||||
stream.on('error', function(err): void {
|
||||
return res.report_error(err);
|
||||
return res.locals.report_error(err);
|
||||
});
|
||||
|
||||
res.header(HEADERS.CONTENT_TYPE, HEADERS.OCTET_STREAM);
|
||||
|
@ -139,7 +139,7 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I
|
||||
storage.mergeTags(packageName, tags, cb);
|
||||
};
|
||||
|
||||
const afterChange = function(error, okMessage, metadata): void {
|
||||
const afterChange = function(error, okMessage, metadata: Package): void {
|
||||
const metadataCopy: Package = { ...metadata };
|
||||
|
||||
const { _attachments, versions } = metadataCopy;
|
||||
@ -326,7 +326,7 @@ export function uploadPackageTarball(storage: IStorageHandler) {
|
||||
});
|
||||
|
||||
stream.on('error', function(err) {
|
||||
return res.report_error(err);
|
||||
return res.locals.report_error(err);
|
||||
});
|
||||
|
||||
stream.on('success', function() {
|
||||
|
@ -74,16 +74,4 @@ export default function(route: Router, auth: IAuth, config: Config): void {
|
||||
ok: API_MESSAGE.LOGGED_OUT,
|
||||
});
|
||||
});
|
||||
|
||||
// placeholder 'cause npm require to be authenticated to publish
|
||||
// we do not do any real authentication yet
|
||||
route.post('/_session', Cookies.express(), function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
res.cookies.set('AuthSession', String(Math.random()), createSessionToken());
|
||||
|
||||
next({
|
||||
ok: true,
|
||||
name: 'somebody',
|
||||
roles: [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
8
packages/api/test/.eslintrc
Normal file
8
packages/api/test/.eslintrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-member-accessibility": 0,
|
||||
"@typescript-eslint/no-unused-vars": 2,
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
70
packages/api/test/integration/_helper.ts
Normal file
70
packages/api/test/integration/_helper.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import path from "path";
|
||||
import express, {Application} from 'express';
|
||||
import supertest from 'supertest';
|
||||
|
||||
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 apiEndpoints from '../../src';
|
||||
import {IAuth} from "@verdaccio/dev-types";
|
||||
import {HEADER_TYPE, HTTP_STATUS, generatePackageMetadata} from "@verdaccio/dev-commons";
|
||||
import {HEADERS} from "@verdaccio/commons-api";
|
||||
|
||||
const getConf = (conf) => {
|
||||
const configPath = path.join(__dirname, 'config', conf);
|
||||
|
||||
return parseConfigFile(configPath);
|
||||
};
|
||||
|
||||
export async function initializeServer(configName): Promise<Application> {
|
||||
const app = express();
|
||||
const config = new Config(getConf(configName));
|
||||
const storage = new Storage(config);
|
||||
await storage.init(config, []);
|
||||
const auth: IAuth = new Auth(config);
|
||||
// @ts-ignore
|
||||
app.use(errorReportingMiddleware);
|
||||
// @ts-ignore
|
||||
app.use(apiEndpoints(config, auth, storage));
|
||||
// @ts-ignore
|
||||
app.use(handleError);
|
||||
// @ts-ignore
|
||||
app.use(final);
|
||||
|
||||
app.use(function(request, response) {
|
||||
response.status(590);
|
||||
console.log('respo', response);
|
||||
response.json({error: 'cannot handle this'});
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
export function publishVersion(app, configFile, pkgName, version): supertest.Test {
|
||||
const pkgMetadata = generatePackageMetadata(pkgName, version);
|
||||
|
||||
return supertest(app)
|
||||
.put(`/${encodeURIComponent(pkgName)}`)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify(pkgMetadata))
|
||||
.set('accept', HEADERS.GZIP)
|
||||
.set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON);
|
||||
}
|
||||
|
||||
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)}`)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify(pkgMetadata))
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.set('accept', HEADERS.GZIP)
|
||||
.set(HEADER_TYPE.ACCEPT_ENCODING, HEADERS.JSON)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON);
|
||||
}
|
30
packages/api/test/integration/config/package.yaml
Normal file
30
packages/api/test/integration/config/package.yaml
Normal file
@ -0,0 +1,30 @@
|
||||
store:
|
||||
memory:
|
||||
limit: 1000
|
||||
|
||||
auth:
|
||||
auth-memory:
|
||||
users:
|
||||
test:
|
||||
name: test
|
||||
password: test
|
||||
|
||||
web:
|
||||
enable: true
|
||||
title: verdaccio
|
||||
|
||||
publish:
|
||||
allow_offline: false
|
||||
|
||||
uplinks:
|
||||
|
||||
logs: { type: stdout, format: pretty, level: trace }
|
||||
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $anonymous
|
||||
publish: $anonymous
|
||||
'**':
|
||||
access: $anonymous
|
||||
publish: $anonymous
|
||||
_debug: true
|
30
packages/api/test/integration/config/ping.yaml
Normal file
30
packages/api/test/integration/config/ping.yaml
Normal file
@ -0,0 +1,30 @@
|
||||
store:
|
||||
memory:
|
||||
limit: 10
|
||||
|
||||
auth:
|
||||
auth-memory:
|
||||
users:
|
||||
web:
|
||||
enable: true
|
||||
title: verdaccio
|
||||
|
||||
uplinks:
|
||||
|
||||
logs: { type: stdout, format: pretty, level: trace }
|
||||
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: $all
|
||||
proxy: npmjs
|
||||
'verdaccio':
|
||||
access: $all
|
||||
publish: $all
|
||||
'**':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: $all
|
||||
proxy: npmjs
|
||||
_debug: true
|
30
packages/api/test/integration/config/publish.yaml
Normal file
30
packages/api/test/integration/config/publish.yaml
Normal file
@ -0,0 +1,30 @@
|
||||
store:
|
||||
memory:
|
||||
limit: 1000
|
||||
|
||||
auth:
|
||||
auth-memory:
|
||||
users:
|
||||
test:
|
||||
name: test
|
||||
password: test
|
||||
|
||||
web:
|
||||
enable: true
|
||||
title: verdaccio
|
||||
|
||||
publish:
|
||||
allow_offline: false
|
||||
|
||||
uplinks:
|
||||
|
||||
logs: { type: stdout, format: pretty, level: trace }
|
||||
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $anonymous
|
||||
publish: $anonymous
|
||||
'**':
|
||||
access: $anonymous
|
||||
publish: $anonymous
|
||||
_debug: true
|
36
packages/api/test/integration/config/user.yaml
Normal file
36
packages/api/test/integration/config/user.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
store:
|
||||
memory:
|
||||
limit: 1000
|
||||
|
||||
auth:
|
||||
auth-memory:
|
||||
users:
|
||||
test:
|
||||
name: test
|
||||
password: test
|
||||
|
||||
web:
|
||||
enable: true
|
||||
title: verdaccio
|
||||
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: https://registry.npmjs.org/
|
||||
|
||||
logs: { type: stdout, format: pretty, level: trace }
|
||||
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: $all
|
||||
proxy: npmjs
|
||||
'verdaccio':
|
||||
access: $all
|
||||
publish: $all
|
||||
'**':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: $all
|
||||
proxy: npmjs
|
||||
_debug: true
|
36
packages/api/test/integration/config/whoami.yaml
Normal file
36
packages/api/test/integration/config/whoami.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
store:
|
||||
memory:
|
||||
limit: 1000
|
||||
|
||||
auth:
|
||||
auth-memory:
|
||||
users:
|
||||
test:
|
||||
name: test
|
||||
password: test
|
||||
|
||||
web:
|
||||
enable: true
|
||||
title: verdaccio
|
||||
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: https://registry.npmjs.org/
|
||||
|
||||
logs: { type: stdout, format: pretty, level: trace }
|
||||
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: $all
|
||||
proxy: npmjs
|
||||
'verdaccio':
|
||||
access: $all
|
||||
publish: $all
|
||||
'**':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: $all
|
||||
proxy: npmjs
|
||||
_debug: true
|
83
packages/api/test/integration/package.spec.ts
Normal file
83
packages/api/test/integration/package.spec.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import supertest from 'supertest';
|
||||
|
||||
import {initializeServer, publishTaggedVersion, publishVersion} from './_helper';
|
||||
import { HTTP_STATUS } from '@verdaccio/commons-api';
|
||||
import {HEADER_TYPE, HEADERS} from '@verdaccio/dev-commons';
|
||||
import {$RequestExtend, $ResponseExtend} from "@verdaccio/dev-types";
|
||||
|
||||
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 {
|
||||
apiJWTmiddleware() {
|
||||
return mockApiJWTmiddleware();
|
||||
}
|
||||
allow_access (_d, f_, cb) {
|
||||
cb(null, true)
|
||||
}
|
||||
allow_publish (_d, f_, cb) {
|
||||
cb(null, true)
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
describe('package', () => {
|
||||
let app;
|
||||
beforeAll(async () => {
|
||||
app = await initializeServer('package.yaml');
|
||||
await publishVersion(app, 'package.yaml', 'foo', '1.0.0');
|
||||
});
|
||||
|
||||
test('should return a package', async (done) => {
|
||||
|
||||
return supertest(app)
|
||||
.get('/foo')
|
||||
.set('Accept', HEADERS.JSON)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.then(response => {
|
||||
expect(response.body.name).toEqual('foo');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should return a package by version', async (done) => {
|
||||
return supertest(app)
|
||||
.get('/foo/1.0.0')
|
||||
.set('Accept', HEADERS.JSON)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.then(response => {
|
||||
expect(response.body.name).toEqual('foo');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: investigate the 404
|
||||
test.skip('should return a package by dist-tag', async (done) => {
|
||||
await publishVersion(app, 'package.yaml', 'foo-tagged', '1.0.0');
|
||||
await publishTaggedVersion(app, 'package.yaml', 'foo-tagged', '1.0.1', 'test');
|
||||
return supertest(app)
|
||||
.get('/foo-tagged/1.0.0')
|
||||
.set('Accept', HEADERS.JSON)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.then(response => {
|
||||
expect(response.body.name).toEqual('foo');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should return 404', async () => {
|
||||
return supertest(app)
|
||||
.get('/404-not-found')
|
||||
.set('Accept', HEADERS.JSON)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.NOT_FOUND);
|
||||
});
|
||||
});
|
16
packages/api/test/integration/ping.spec.ts
Normal file
16
packages/api/test/integration/ping.spec.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import supertest from 'supertest';
|
||||
|
||||
import {initializeServer } from './_helper';
|
||||
import { HTTP_STATUS } from '@verdaccio/commons-api';
|
||||
import {HEADER_TYPE, HEADERS} from '@verdaccio/dev-commons';
|
||||
|
||||
describe('ping', () => {
|
||||
test('should return the reply the ping', async () => {
|
||||
return supertest(await initializeServer('ping.yaml'))
|
||||
.get('/-/ping')
|
||||
.set('Accept', HEADERS.JSON)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.then(response => expect(response.body).toEqual({}));
|
||||
});
|
||||
});
|
179
packages/api/test/integration/publish.spec.ts
Normal file
179
packages/api/test/integration/publish.spec.ts
Normal file
@ -0,0 +1,179 @@
|
||||
import {initializeServer, publishVersion} from './_helper';
|
||||
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";
|
||||
|
||||
const mockApiJWTmiddleware = jest.fn(() =>
|
||||
(req: $RequestExtend, res: $ResponseExtend, _next): void => {
|
||||
req.remote_user = { name: 'foo', groups: [], real_groups: []}
|
||||
_next();
|
||||
}
|
||||
);
|
||||
|
||||
jest.setTimeout(50000000);
|
||||
|
||||
jest.mock('@verdaccio/auth', () => ({
|
||||
Auth: class {
|
||||
apiJWTmiddleware() {
|
||||
return mockApiJWTmiddleware();
|
||||
}
|
||||
allow_access (_d, f_, cb) {
|
||||
cb(null, true)
|
||||
}
|
||||
allow_publish (_d, f_, cb) {
|
||||
cb(null, true)
|
||||
}
|
||||
|
||||
allow_unpublish (_d, f_, cb) {
|
||||
cb(null, true)
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// const mockStorage = jest.fn(() => {
|
||||
// const { Storage } = jest.requireActual('@verdaccio/store');
|
||||
// return {
|
||||
// Storage: class extends Storage {
|
||||
// addPackage(name, metadata, cb) {
|
||||
// super.addPackage(name, metadata, cb);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
|
||||
// jest.mock('@verdaccio/store', () => {
|
||||
// const { Storage } = jest.requireActual('@verdaccio/store');
|
||||
// return ({
|
||||
// Storage: class extends Storage {
|
||||
// addPackage(name, metadata, cb) {
|
||||
// // super.addPackage(name, metadata, cb);
|
||||
// return mockStorage(name, metadata, cb);
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
|
||||
describe('publish', () => {
|
||||
describe('handle invalid publish formats', () => {
|
||||
const pkgName = 'test';
|
||||
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
|
||||
test('should fail on publish a bad _attachments package', async (done) => {
|
||||
const app = await initializeServer('publish.yaml');
|
||||
return supertest(app)
|
||||
.put(`/${encodeURIComponent(pkgName)}`)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify(Object.assign({}, pkgMetadata, {
|
||||
_attachments: {}
|
||||
})))
|
||||
.set('accept', HEADERS.GZIP)
|
||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
||||
.then(response => {
|
||||
console.log("response.body", response.body);
|
||||
expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should fail on publish a bad versions package', async (done) => {
|
||||
const app = await initializeServer('publish.yaml');
|
||||
return supertest(app)
|
||||
.put(`/${encodeURIComponent(pkgName)}`)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify(Object.assign({}, pkgMetadata, {
|
||||
versions: ''
|
||||
})))
|
||||
.set('accept', HEADERS.GZIP)
|
||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
||||
.then(response => {
|
||||
console.log("response.body", response.body);
|
||||
expect(response.body.error).toEqual(API_ERROR.UNSUPORTED_REGISTRY_CALL);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('publish a package', () => {
|
||||
test('should publish a package', async (done) => {
|
||||
const app = await initializeServer('publish.yaml');
|
||||
return publishVersion(app, 'publish.yaml', 'foo', '1.0.0')
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.then(response => {
|
||||
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should publish a new package', async (done) => {
|
||||
const pkgName = 'test';
|
||||
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
|
||||
const app = await initializeServer('publish.yaml');
|
||||
return supertest(app)
|
||||
.put(`/${encodeURIComponent(pkgName)}`)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify(Object.assign({}, pkgMetadata, {
|
||||
_attachments: null
|
||||
})))
|
||||
.set('accept', HEADERS.GZIP)
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.then(response => {
|
||||
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should publish a new package with no readme', async (done) => {
|
||||
const pkgName = 'test';
|
||||
const pkgMetadata = generatePackageMetadata(pkgName, '1.0.0');
|
||||
const app = await initializeServer('publish.yaml');
|
||||
return supertest(app)
|
||||
.put(`/${encodeURIComponent(pkgName)}`)
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
.send(JSON.stringify(Object.assign({}, pkgMetadata, {
|
||||
versions: {
|
||||
['1.0.0'] : {
|
||||
readme: null
|
||||
}
|
||||
}
|
||||
})))
|
||||
.set('accept', HEADERS.GZIP)
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.then(response => {
|
||||
expect(response.body.ok).toEqual(API_MESSAGE.PKG_CREATED);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
test('should fails on publish a duplicated package', async (done) => {
|
||||
const app = await initializeServer('publish.yaml');
|
||||
await publishVersion(app, 'publish.yaml', 'foo', '1.0.0');
|
||||
return publishVersion(app, 'publish.yaml', 'foo', '1.0.0')
|
||||
.expect(HTTP_STATUS.CONFLICT)
|
||||
.then(response => {
|
||||
console.log("response.body", response.body);
|
||||
expect(response.body.error).toEqual(API_ERROR.PACKAGE_EXIST);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('unpublish a package', () => {
|
||||
let app;
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await initializeServer('publish.yaml');
|
||||
await publishVersion(app, 'publish.yaml', 'foo', '1.0.0');
|
||||
})
|
||||
|
||||
test('should unpublish a package', () => {
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
describe('star a package', () => {
|
||||
|
||||
});
|
||||
|
||||
});
|
237
packages/api/test/integration/user.spec.ts
Normal file
237
packages/api/test/integration/user.spec.ts
Normal file
@ -0,0 +1,237 @@
|
||||
import supertest from 'supertest';
|
||||
|
||||
import { initializeServer } from './_helper';
|
||||
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/lib";
|
||||
import _ from "lodash";
|
||||
|
||||
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']);
|
||||
}
|
||||
);
|
||||
|
||||
const mockAddUser = jest.fn(() => (_name, _password, callback): void => {
|
||||
return callback(getConflict(API_ERROR.USERNAME_ALREADY_REGISTERED));
|
||||
}
|
||||
);
|
||||
|
||||
jest.mock('@verdaccio/auth', () => ({
|
||||
getApiToken: () => 'token',
|
||||
Auth: class {
|
||||
apiJWTmiddleware() {
|
||||
return mockApiJWTmiddleware();
|
||||
}
|
||||
allow_access (_d, f_, cb) {
|
||||
cb(null, true);
|
||||
}
|
||||
add_user (name, password, callback) {
|
||||
mockAddUser()(name, password, callback);
|
||||
}
|
||||
authenticate (_name, _password, callback) {
|
||||
mockAuthenticate()(_name, _password, callback);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
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();
|
||||
}
|
||||
);
|
||||
|
||||
mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => {
|
||||
return callback(null, true);
|
||||
}
|
||||
);
|
||||
supertest(await initializeServer('user.yaml'))
|
||||
.put(`/-/user/org.couchdb.user:newUser`)
|
||||
.send({
|
||||
name: 'newUser',
|
||||
password: 'newUser'
|
||||
})
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
expect(res.body.ok).toBeDefined();
|
||||
expect(res.body.token).toBeDefined();
|
||||
const token = res.body.token;
|
||||
expect(typeof token).toBe('string');
|
||||
expect(res.body.ok).toMatch(`user 'newUser' created`);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
);
|
||||
supertest(await initializeServer('user.yaml'))
|
||||
.put('/-/user/org.couchdb.user:jotaNew')
|
||||
.send(credentials)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.CONFLICT)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(API_ERROR.USERNAME_ALREADY_REGISTERED);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should log in as existing user', async (done) => {
|
||||
supertest(await initializeServer('user.yaml'))
|
||||
.put(`/-/user/org.couchdb.user:${credentials.name}`)
|
||||
.send(credentials)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.end((err, res) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body).toBeTruthy();
|
||||
expect(res.body.ok).toMatch(`you are authenticated as \'${credentials.name}\'`);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
);
|
||||
mockAddUser.mockImplementationOnce(() => (_name, _password, callback): void => {
|
||||
return callback(getBadRequest(API_ERROR.USERNAME_PASSWORD_REQUIRED));
|
||||
}
|
||||
);
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
delete credentialsShort.name;
|
||||
|
||||
supertest(await initializeServer('user.yaml'))
|
||||
.put(`/-/user/org.couchdb.user:${credentials.name}`)
|
||||
.send(credentialsShort)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(API_ERROR.USERNAME_PASSWORD_REQUIRED);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
);
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
delete credentialsShort.password;
|
||||
|
||||
supertest(await initializeServer('user.yaml'))
|
||||
.put(`/-/user/org.couchdb.user:${credentials.name}`)
|
||||
.send(credentialsShort)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body.error).toBeDefined();
|
||||
// FIXME: message is not 100% accurate
|
||||
// eslint-disable-next-line new-cap
|
||||
expect(res.body.error).toMatch(API_ERROR.PASSWORD_SHORT());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
);
|
||||
mockAuthenticate.mockImplementationOnce(() => (_name, _password, callback): void => {
|
||||
return callback(getUnauthorized(API_ERROR.BAD_USERNAME_PASSWORD));
|
||||
}
|
||||
);
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
credentialsShort.password = 'failPassword';
|
||||
|
||||
supertest(await initializeServer('user.yaml'))
|
||||
.put('/-/user/org.couchdb.user:test')
|
||||
.send(credentialsShort)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.UNAUTHORIZED)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(API_ERROR.BAD_USERNAME_PASSWORD);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should be able to logout an user', async (done) => {
|
||||
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));
|
||||
}
|
||||
);
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
credentialsShort.password = 'failPassword';
|
||||
|
||||
supertest(await initializeServer('user.yaml'))
|
||||
.delete('/-/user/token/someSecretToken')
|
||||
.send(credentialsShort)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body.ok).toMatch(API_MESSAGE.LOGGED_OUT);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
53
packages/api/test/integration/whoami.spec.ts
Normal file
53
packages/api/test/integration/whoami.spec.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import supertest from 'supertest';
|
||||
|
||||
import {initializeServer } from './_helper';
|
||||
import { HTTP_STATUS } from '@verdaccio/commons-api';
|
||||
import { HEADERS} from '@verdaccio/dev-commons';
|
||||
import {$RequestExtend, $ResponseExtend} from "@verdaccio/dev-types";
|
||||
|
||||
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 {
|
||||
apiJWTmiddleware() {
|
||||
return mockApiJWTmiddleware();
|
||||
}
|
||||
allow_access (_d, f_, cb) {
|
||||
cb(null, true)
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
describe('whoami', () => {
|
||||
test.skip('should test referer /whoami endpoint', async (done) => {
|
||||
return supertest(await initializeServer('whoami.yaml'))
|
||||
.get('/whoami')
|
||||
.set('referer', 'whoami')
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(done);
|
||||
});
|
||||
|
||||
test.skip('should test no referer /whoami endpoint', async (done) => {
|
||||
return supertest(await initializeServer('whoami.yaml'))
|
||||
.get('/whoami')
|
||||
.expect(HTTP_STATUS.NOT_FOUND)
|
||||
.end(done);
|
||||
});
|
||||
|
||||
|
||||
test('should return the logged username', async () => {
|
||||
return supertest(await initializeServer('whoami.yaml'))
|
||||
.get('/-/whoami')
|
||||
.set('Accept', HEADERS.JSON)
|
||||
.expect('Content-Type', HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.then(response => {
|
||||
expect(response.body.username).toEqual('foo');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { addVersion, uploadPackageTarball, removeTarball, unPublishPackage, publishPackage } from '../src/publish';
|
||||
import { addVersion, uploadPackageTarball, removeTarball, unPublishPackage, publishPackage } from '../../src/publish';
|
||||
import { HTTP_STATUS, API_ERROR } from '@verdaccio/dev-commons';
|
||||
|
||||
const REVISION_MOCK = '15-e53a77096b0ee33e';
|
||||
@ -82,7 +82,7 @@ describe('Publish endpoints - upload package tarball', () => {
|
||||
pipe: jest.fn(),
|
||||
on: jest.fn(),
|
||||
};
|
||||
res = { status: jest.fn(), report_error: jest.fn() };
|
||||
res = { status: jest.fn(), locals: { report_error: jest.fn() }};
|
||||
next = jest.fn();
|
||||
});
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable curly */
|
||||
// ensure that all arguments are validated
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
@ -13,7 +14,7 @@ import fs from 'fs';
|
||||
*/
|
||||
describe('api endpoint app.param()', () => {
|
||||
let m;
|
||||
const requirePath = path.normalize(path.join(__dirname, '../src/index.ts'));
|
||||
const requirePath = path.normalize(path.join(__dirname, '../../src/index.ts'));
|
||||
const source = fs.readFileSync(requirePath, 'utf8');
|
||||
const very_scary_regexp = /\n\s*app\.(\w+)\s*\(\s*(("[^"]*")|('[^']*'))\s*,/g;
|
||||
const appParams = {};
|
@ -23,7 +23,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@verdaccio/commons-api": "9.4.0",
|
||||
"@verdaccio/commons-api": "9.6.1",
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"@verdaccio/loaders": "5.0.0-alpha.0",
|
||||
"@verdaccio/logger": "5.0.0-alpha.0",
|
||||
|
@ -31,7 +31,7 @@
|
||||
"@verdaccio/config": "5.0.0-alpha.0",
|
||||
"@verdaccio/node-api": "5.0.0-alpha.0",
|
||||
"@verdaccio/utils": "5.0.0-alpha.0",
|
||||
"commander": "3.0.2",
|
||||
"commander": "5.1.0",
|
||||
"envinfo": "7.4.0",
|
||||
"kleur": "3.0.3",
|
||||
"semver": "7.3.2"
|
||||
|
@ -1,12 +1,16 @@
|
||||
import { Package } from "@verdaccio/types";
|
||||
|
||||
export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Package {
|
||||
export interface DistTags {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export function generatePackageMetadata(pkgName: string, version = '1.0.0', distTags: DistTags = {['latest']: version}): Package {
|
||||
// @ts-ignore
|
||||
return {
|
||||
"_id": pkgName,
|
||||
"name": pkgName,
|
||||
"dist-tags": {
|
||||
"latest": version
|
||||
...distTags
|
||||
},
|
||||
"versions": {
|
||||
[version]: {
|
||||
|
@ -15,14 +15,14 @@
|
||||
"license": "MIT",
|
||||
"homepage": "https://verdaccio.org",
|
||||
"dependencies": {
|
||||
"@verdaccio/commons-api": "9.4.0",
|
||||
"@verdaccio/commons-api": "9.6.1",
|
||||
"@verdaccio/logger": "5.0.0-alpha.0",
|
||||
"handlebars": "4.5.3",
|
||||
"request": "2.87.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"@verdaccio/types": "9.3.0"
|
||||
"@verdaccio/types": "9.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./build",
|
||||
|
@ -24,7 +24,7 @@
|
||||
"build": "npm run build:js && npm run build:types"
|
||||
},
|
||||
"dependencies": {
|
||||
"@verdaccio/commons-api": "9.4.0",
|
||||
"@verdaccio/commons-api": "9.6.1",
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"dayjs": "1.8.19",
|
||||
"fast-safe-stringify": "2.0.7",
|
||||
|
@ -29,7 +29,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/pino": "6.0.1",
|
||||
"@verdaccio/types": "9.3.0"
|
||||
"@verdaccio/types": "9.5.0"
|
||||
},
|
||||
"gitHead": "7c246ede52ff717707fcae66dd63fc4abd536982"
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
"build": "npm run build:js && npm run build:types"
|
||||
},
|
||||
"dependencies": {
|
||||
"@verdaccio/commons-api": "9.4.0",
|
||||
"@verdaccio/commons-api": "9.6.1",
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"@verdaccio/logger": "5.0.0-alpha.0",
|
||||
"@verdaccio/utils": "5.0.0-alpha.0",
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import {
|
||||
@ -13,6 +14,7 @@ import { $ResponseExtend, $RequestExtend, $NextFunctionVer, IAuth } from '@verda
|
||||
import { Config, Package, RemoteUser } from '@verdaccio/types';
|
||||
import { logger } from '@verdaccio/logger';
|
||||
import { VerdaccioError } from '@verdaccio/commons-api';
|
||||
import {HttpError} from "http-errors";
|
||||
|
||||
export function match(regexp: RegExp): any {
|
||||
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer, value: string): void {
|
||||
@ -110,8 +112,7 @@ export function allow(auth: IAuth): Function {
|
||||
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}`);
|
||||
|
||||
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) {
|
||||
@ -148,7 +149,8 @@ export function final(body: FinalBody, req: $RequestExtend, res: $ResponseExtend
|
||||
|
||||
if (typeof body === 'object' && _.isNil(body) === false) {
|
||||
if (typeof (body as MiddlewareError).error === 'string') {
|
||||
res._verdaccio_error = (body as MiddlewareError).error;
|
||||
res.locals._verdaccio_error = (body as MiddlewareError).error;
|
||||
// res._verdaccio_error = (body as MiddlewareError).error;
|
||||
}
|
||||
body = JSON.stringify(body, undefined, ' ') + '\n';
|
||||
}
|
||||
@ -181,121 +183,122 @@ export const LOG_STATUS_MESSAGE = "@{status}, user: @{user}(@{remoteIP}), req: '
|
||||
export const LOG_VERDACCIO_ERROR = `${LOG_STATUS_MESSAGE}, error: @{!error}`;
|
||||
export const LOG_VERDACCIO_BYTES = `${LOG_STATUS_MESSAGE}, bytes: @{bytes.in}/@{bytes.out}`;
|
||||
|
||||
export function log(config: Config) {
|
||||
return function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
// logger
|
||||
req.log = logger.child({ sub: 'in' });
|
||||
export function log(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
// logger
|
||||
req.log = logger.child({ sub: 'in' });
|
||||
|
||||
const _auth = req.headers.authorization;
|
||||
if (_.isNil(_auth) === false) {
|
||||
req.headers.authorization = '<Classified>';
|
||||
}
|
||||
const _auth = req.headers.authorization;
|
||||
if (_.isNil(_auth) === false) {
|
||||
req.headers.authorization = '<Classified>';
|
||||
}
|
||||
|
||||
const _cookie = req.headers.cookie;
|
||||
if (_.isNil(_cookie) === false) {
|
||||
req.headers.cookie = '<Classified>';
|
||||
const _cookie = req.headers.cookie;
|
||||
if (_.isNil(_cookie) === false) {
|
||||
req.headers.cookie = '<Classified>';
|
||||
}
|
||||
|
||||
req.url = req.originalUrl;
|
||||
req.log.info({ req: req, ip: req.ip }, "@{ip} requested '@{req.method} @{req.url}'");
|
||||
req.originalUrl = req.url;
|
||||
|
||||
if (_.isNil(_auth) === false) {
|
||||
req.headers.authorization = _auth;
|
||||
}
|
||||
|
||||
if (_.isNil(_cookie) === false) {
|
||||
req.headers.cookie = _cookie;
|
||||
}
|
||||
|
||||
let bytesin = 0;
|
||||
req.on('data', function(chunk): void {
|
||||
bytesin += chunk.length;
|
||||
});
|
||||
|
||||
let bytesout = 0;
|
||||
const _write = res.write;
|
||||
// FIXME: res.write should return boolean
|
||||
// @ts-ignore
|
||||
res.write = function(buf): boolean {
|
||||
bytesout += buf.length;
|
||||
/* eslint prefer-rest-params: "off" */
|
||||
// @ts-ignore
|
||||
_write.apply(res, arguments);
|
||||
};
|
||||
|
||||
const log = function(): void {
|
||||
const forwardedFor = req.headers['x-forwarded-for'];
|
||||
const remoteAddress = req.connection.remoteAddress;
|
||||
const remoteIP = forwardedFor ? `${forwardedFor} via ${remoteAddress}` : remoteAddress;
|
||||
let message;
|
||||
if (res.locals._verdaccio_error) {
|
||||
message = LOG_VERDACCIO_ERROR;
|
||||
} else {
|
||||
message = LOG_VERDACCIO_BYTES;
|
||||
}
|
||||
|
||||
req.url = req.originalUrl;
|
||||
// avoid log noise data from static content
|
||||
if (req.originalUrl.match(/static/) === null) {
|
||||
req.log.info({req: req, ip: req.ip}, "@{ip} requested '@{req.method} @{req.url}'");
|
||||
}
|
||||
req.log.warn(
|
||||
{
|
||||
request: {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
},
|
||||
level: 35, // http
|
||||
user: (req.remote_user && req.remote_user.name) || null,
|
||||
remoteIP,
|
||||
status: res.statusCode,
|
||||
error: res.locals._verdaccio_error,
|
||||
bytes: {
|
||||
in: bytesin,
|
||||
out: bytesout,
|
||||
},
|
||||
},
|
||||
message
|
||||
);
|
||||
req.originalUrl = req.url;
|
||||
};
|
||||
|
||||
if (_.isNil(_auth) === false) {
|
||||
req.headers.authorization = _auth;
|
||||
}
|
||||
req.on('close', function(): void {
|
||||
log();
|
||||
});
|
||||
|
||||
if (_.isNil(_cookie) === false) {
|
||||
req.headers.cookie = _cookie;
|
||||
}
|
||||
|
||||
let bytesin = 0;
|
||||
if (config?.experiments?.bytesin_off !== true) {
|
||||
req.on('data', function(chunk): void {
|
||||
bytesin += chunk.length;
|
||||
});
|
||||
}
|
||||
|
||||
let bytesout = 0;
|
||||
const _write = res.write;
|
||||
// FIXME: res.write should return boolean
|
||||
// @ts-ignore
|
||||
res.write = function(buf): boolean {
|
||||
const _end = res.end;
|
||||
res.end = function(buf): void {
|
||||
if (buf) {
|
||||
bytesout += buf.length;
|
||||
/* eslint prefer-rest-params: "off" */
|
||||
// @ts-ignore
|
||||
_write.apply(res, arguments);
|
||||
};
|
||||
|
||||
let logHasBeenCalled = false;
|
||||
const log = function(): void {
|
||||
if (logHasBeenCalled) {
|
||||
return;
|
||||
}
|
||||
logHasBeenCalled = true;
|
||||
|
||||
const forwardedFor = req.headers['x-forwarded-for'];
|
||||
const remoteAddress = req.connection.remoteAddress;
|
||||
const remoteIP = forwardedFor ? `${forwardedFor} via ${remoteAddress}` : remoteAddress;
|
||||
let message;
|
||||
if (res._verdaccio_error) {
|
||||
message = LOG_VERDACCIO_ERROR;
|
||||
} else {
|
||||
message = LOG_VERDACCIO_BYTES;
|
||||
}
|
||||
|
||||
req.url = req.originalUrl;
|
||||
// avoid log noise data from static content
|
||||
if (req.url.match(/static/) === null) {
|
||||
req.log.warn(
|
||||
{
|
||||
request: {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
},
|
||||
level: 35, // http
|
||||
user: (req.remote_user && req.remote_user.name) || null,
|
||||
remoteIP,
|
||||
status: res.statusCode,
|
||||
error: res._verdaccio_error,
|
||||
bytes: {
|
||||
in: bytesin,
|
||||
out: bytesout,
|
||||
},
|
||||
},
|
||||
message
|
||||
);
|
||||
req.originalUrl = req.url;
|
||||
}
|
||||
}
|
||||
/* eslint prefer-rest-params: "off" */
|
||||
// @ts-ignore
|
||||
_end.apply(res, arguments);
|
||||
log();
|
||||
};
|
||||
next();
|
||||
}
|
||||
|
||||
req.on('close', function(): void {
|
||||
log();
|
||||
});
|
||||
|
||||
const _end = res.end;
|
||||
res.end = function(buf): void {
|
||||
if (buf) {
|
||||
bytesout += buf.length;
|
||||
}
|
||||
/* eslint prefer-rest-params: "off" */
|
||||
// @ts-ignore
|
||||
_end.apply(res, arguments);
|
||||
log();
|
||||
};
|
||||
next();
|
||||
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();
|
||||
}
|
||||
if (_.isFunction(res.locals.report_error) === false) {
|
||||
// in case of very early error this middleware may not be loaded before error is generated
|
||||
// fixing that
|
||||
errorReportingMiddleware(req, res, _.noop);
|
||||
}
|
||||
res.locals.report_error(err);
|
||||
} else {
|
||||
// Fall to Middleware.final
|
||||
return next(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware
|
||||
export function errorReportingMiddleware(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
res.report_error =
|
||||
res.report_error ||
|
||||
res.locals.report_error =
|
||||
res.locals.report_error ||
|
||||
function(err: VerdaccioError): void {
|
||||
if (err.status && err.status >= HTTP_STATUS.BAD_REQUEST && err.status < 600) {
|
||||
if (!res.headersSent) {
|
||||
if (_.isNil(res.headersSent) === false) {
|
||||
res.status(err.status);
|
||||
next({ error: err.message || API_ERROR.UNKNOWN_ERROR });
|
||||
}
|
||||
|
14
packages/middleware/types/custom.d.ts
vendored
14
packages/middleware/types/custom.d.ts
vendored
@ -1,4 +1,7 @@
|
||||
// <reference types="node" />
|
||||
|
||||
import { Logger, RemoteUser } from "@verdaccio/types";
|
||||
import * as http from "http";
|
||||
|
||||
declare global {
|
||||
namespace Express {
|
||||
@ -7,10 +10,11 @@ declare global {
|
||||
log: Logger;
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
report_error: any;
|
||||
_verdaccio_error: any;
|
||||
socket?: any;
|
||||
}
|
||||
// FIXME:
|
||||
// export interface Response extends http.ServerResponse, Express.Response {
|
||||
// report_error: any;
|
||||
// _verdaccio_error: any;
|
||||
// socket?: any;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -24,16 +24,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"@verdaccio/local-storage": "9.5.0",
|
||||
"@verdaccio/local-storage": "9.6.1",
|
||||
"@verdaccio/logger": "5.0.0-alpha.0",
|
||||
"@verdaccio/streams": "9.5.0",
|
||||
"@verdaccio/streams": "9.6.1",
|
||||
"@verdaccio/utils": "5.0.0-alpha.0",
|
||||
"JSONStream": "1.3.5",
|
||||
"request": "2.87.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@verdaccio/dev-types": "5.0.0-alpha.0",
|
||||
"@verdaccio/types": "9.3.0"
|
||||
"@verdaccio/types": "9.5.0"
|
||||
},
|
||||
"gitHead": "7c246ede52ff717707fcae66dd63fc4abd536982"
|
||||
}
|
||||
|
@ -85,12 +85,12 @@ const defineAPI = function(config: IConfig, storage: IStorageHandler): any {
|
||||
if (err.code === 'ECONNABORT' && res.statusCode === HTTP_STATUS.NOT_MODIFIED) {
|
||||
return next();
|
||||
}
|
||||
if (_.isFunction(res.report_error) === false) {
|
||||
if (_.isFunction(res.locals.report_error) === false) {
|
||||
// in case of very early error this middleware may not be loaded before error is generated
|
||||
// fixing that
|
||||
errorReportingMiddleware(req, res, _.noop);
|
||||
}
|
||||
res.report_error(err);
|
||||
res.locals.report_error(err);
|
||||
} else {
|
||||
// Fall to Middleware.final
|
||||
return next(err);
|
||||
|
8
packages/server/test/.eslintrc
Normal file
8
packages/server/test/.eslintrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-member-accessibility": 0,
|
||||
"@typescript-eslint/no-unused-vars": 2,
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ import path from 'path';
|
||||
import endPointAPI from '@verdaccio/server';
|
||||
import {
|
||||
HEADERS,
|
||||
API_ERROR,
|
||||
HTTP_STATUS,
|
||||
HEADER_TYPE,
|
||||
API_MESSAGE,
|
||||
@ -85,67 +84,7 @@ describe('endpoint unit test', () => {
|
||||
});
|
||||
|
||||
describe('Registry API Endpoints', () => {
|
||||
|
||||
describe('should test ping api', () => {
|
||||
test('should test endpoint /-/ping', (done) => {
|
||||
request(app)
|
||||
.get('/-/ping')
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function(err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('should test whoami api', () => {
|
||||
test('should test referer /whoami endpoint', (done) => {
|
||||
request(app)
|
||||
.get('/whoami')
|
||||
.set('referer', 'whoami')
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(done);
|
||||
});
|
||||
|
||||
test('should test no referer /whoami endpoint', (done) => {
|
||||
request(app)
|
||||
.get('/whoami')
|
||||
.expect(HTTP_STATUS.NOT_FOUND)
|
||||
.end(done);
|
||||
});
|
||||
|
||||
test('should test /-/whoami endpoint', (done) => {
|
||||
request(app)
|
||||
.get('/-/whoami')
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function(err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should test /whoami endpoint', (done) => {
|
||||
request(app)
|
||||
.get('/-/whoami')
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function(err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('should test user api', () => {
|
||||
|
||||
describe('should test authorization headers with tokens only errors', () => {
|
||||
test('should fails on protected endpoint /-/auth-package bad format', (done) => {
|
||||
request(app)
|
||||
@ -219,106 +158,6 @@ describe('endpoint unit test', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('should test fails add a new user with missing name', (done) => {
|
||||
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
delete credentialsShort.name;
|
||||
|
||||
request(app)
|
||||
.put(`/-/user/org.couchdb.user:${credentials.name}`)
|
||||
.send(credentialsShort)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(API_ERROR.USERNAME_PASSWORD_REQUIRED);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should test fails add a new user with missing password', (done) => {
|
||||
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
delete credentialsShort.password;
|
||||
|
||||
request(app)
|
||||
.put(`/-/user/org.couchdb.user:${credentials.name}`)
|
||||
.send(credentialsShort)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body.error).toBeDefined();
|
||||
// FIXME: message is not 100% accurate
|
||||
/* eslint new-cap: 0 */
|
||||
expect(res.body.error).toMatch(API_ERROR.PASSWORD_SHORT());
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should test add a new user with login', (done) => {
|
||||
const newCredentials = _.cloneDeep(credentials);
|
||||
newCredentials.name = 'jotaNew';
|
||||
|
||||
request(app)
|
||||
.put('/-/user/org.couchdb.user:jotaNew')
|
||||
.send(newCredentials)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.CREATED)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
expect(res.body).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should test fails on add a existing user with login', (done) => {
|
||||
request(app)
|
||||
.put('/-/user/org.couchdb.user:jotaNew')
|
||||
.send(credentials)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.CONFLICT)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(API_ERROR.USERNAME_ALREADY_REGISTERED);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('should test fails add a new user with wrong password', (done) => {
|
||||
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
credentialsShort.password = 'failPassword';
|
||||
|
||||
request(app)
|
||||
.put('/-/user/org.couchdb.user:jota')
|
||||
.send(credentialsShort)
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.UNAUTHORIZED)
|
||||
.end(function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(/unauthorized/);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('should test package api', () => {
|
||||
|
6
packages/server/types/custom.d.ts
vendored
6
packages/server/types/custom.d.ts
vendored
@ -6,11 +6,5 @@ declare global {
|
||||
remote_user: RemoteUser;
|
||||
log: Logger;
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
report_error: any;
|
||||
_verdaccio_error: any;
|
||||
socket?: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,20 +23,20 @@
|
||||
"build": "npm run build:js && npm run build:types"
|
||||
},
|
||||
"dependencies": {
|
||||
"@verdaccio/commons-api": "9.4.0",
|
||||
"@verdaccio/commons-api": "9.6.1",
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"@verdaccio/loaders": "5.0.0-alpha.0",
|
||||
"@verdaccio/local-storage": "9.5.0",
|
||||
"@verdaccio/local-storage": "9.6.1",
|
||||
"@verdaccio/logger": "5.0.0-alpha.0",
|
||||
"@verdaccio/proxy": "5.0.0-alpha.0",
|
||||
"@verdaccio/streams": "9.5.0",
|
||||
"@verdaccio/streams": "9.6.1",
|
||||
"@verdaccio/utils": "5.0.0-alpha.0",
|
||||
"async": "3.1.1",
|
||||
"lodash": "4.17.15",
|
||||
"semver": "7.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@verdaccio/types": "9.3.0"
|
||||
"@verdaccio/types": "9.5.0"
|
||||
},
|
||||
"gitHead": "7c246ede52ff717707fcae66dd63fc4abd536982"
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
"homepage": "https://verdaccio.org",
|
||||
"dependencies": {
|
||||
"@verdaccio/dev-commons": "5.0.0-alpha.0",
|
||||
"@verdaccio/readme": "9.5.0",
|
||||
"@verdaccio/readme": "9.6.1",
|
||||
"js-yaml": "3.13.1",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"minimatch": "3.0.4",
|
||||
|
8
packages/utils/test/.eslintrc
Normal file
8
packages/utils/test/.eslintrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-member-accessibility": 0,
|
||||
"no-console": 0,
|
||||
"@typescript-eslint/no-unused-vars": 1
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@verdaccio/dev-types": "5.0.0-alpha.0",
|
||||
"@verdaccio/types": "9.3.0"
|
||||
"@verdaccio/types": "9.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf ./build",
|
||||
|
6
packages/web/types/custom.d.ts
vendored
6
packages/web/types/custom.d.ts
vendored
@ -6,11 +6,5 @@ declare global {
|
||||
remote_user: RemoteUser;
|
||||
log: Logger;
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
report_error: any;
|
||||
_verdaccio_error: any;
|
||||
socket?: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"noImplicitAny": false,
|
||||
"incremental": true,
|
||||
"incremental": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"resolveJsonModule": true,
|
||||
|
BIN
yarn.lock
BIN
yarn.lock
Binary file not shown.
Loading…
Reference in New Issue
Block a user