mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-02-21 07:29:37 +01:00
Merge remote-tracking branch 'origin/master' into 4.1.x
This commit is contained in:
commit
0fa26293a8
@ -14,4 +14,5 @@ Dockerfile
|
||||
*.scss
|
||||
*.png
|
||||
*.jpg
|
||||
*.sh
|
||||
test/unit/partials/
|
||||
|
40
CHANGELOG.md
40
CHANGELOG.md
@ -2,6 +2,46 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [4.0.2](https://github.com/verdaccio/verdaccio/compare/v4.0.1...v4.0.2) (2019-06-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correctly check if the proxy setting evaluates to false ([#1336](https://github.com/verdaccio/verdaccio/issues/1336)) ([df834f4](https://github.com/verdaccio/verdaccio/commit/df834f4))
|
||||
* update dependencies ([e581634](https://github.com/verdaccio/verdaccio/commit/e581634)), closes [#1339](https://github.com/verdaccio/verdaccio/issues/1339)
|
||||
* update security policy details ([#1342](https://github.com/verdaccio/verdaccio/issues/1342)) ([ddcd89d](https://github.com/verdaccio/verdaccio/commit/ddcd89d))
|
||||
* **api:** force authenticate on login ([#1347](https://github.com/verdaccio/verdaccio/issues/1347)) ([85c1bd1](https://github.com/verdaccio/verdaccio/commit/85c1bd1))
|
||||
* **ui:** failed to load all packages after login ([192fb77](https://github.com/verdaccio/verdaccio/commit/192fb77))
|
||||
|
||||
|
||||
|
||||
## [4.0.1](https://github.com/verdaccio/verdaccio/compare/v4.0.0...v4.0.1) (2019-05-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **web:** fix sidebar tarball protocol ([#1326](https://github.com/verdaccio/verdaccio/issues/1326)) ([de04463](https://github.com/verdaccio/verdaccio/commit/de04463)), closes [#1320](https://github.com/verdaccio/verdaccio/issues/1320)
|
||||
|
||||
|
||||
|
||||
# [4.0.0](https://github.com/verdaccio/verdaccio/compare/v4.0.0-beta.8...v4.0.0) (2019-05-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing pkg version and name on start up ([8cf3966](https://github.com/verdaccio/verdaccio/commit/8cf3966))
|
||||
* update @verdaccio/ui-theme:0.1.7 ([8e48eea](https://github.com/verdaccio/verdaccio/commit/8e48eea))
|
||||
* warning text is hard to read when running under root ([3ac038f](https://github.com/verdaccio/verdaccio/commit/3ac038f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* create security policy ([#1322](https://github.com/verdaccio/verdaccio/issues/1322)) ([0e9f23d](https://github.com/verdaccio/verdaccio/commit/0e9f23d))
|
||||
* prepare release v4 ([#1307](https://github.com/verdaccio/verdaccio/issues/1307)) ([b9506d6](https://github.com/verdaccio/verdaccio/commit/b9506d6))
|
||||
* update readme v4 ([#1312](https://github.com/verdaccio/verdaccio/issues/1312)) ([7686417](https://github.com/verdaccio/verdaccio/commit/7686417))
|
||||
|
||||
|
||||
|
||||
# [4.0.0-beta.10](https://github.com/verdaccio/verdaccio/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2019-05-20)
|
||||
|
||||
|
||||
|
48
README.md
48
README.md
@ -1,6 +1,6 @@
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
# Version 4
|
||||
|
||||
@ -14,8 +14,7 @@ Google Cloud Storage** or create your own plugin.
|
||||
|
||||
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://www.npmjs.com/package/verdaccio)
|
||||
[](https://verdaccio.org/docs/en/docker.html)
|
||||
[](https://opencollective.com/verdaccio)
|
||||
[](https://stackshare.io/verdaccio)
|
||||
@ -82,7 +81,7 @@ $ npm set registry http://localhost:4873/
|
||||
|
||||
Now you can navigate to [http://localhost:4873/](http://localhost:4873/) where your local packages will be listed and can be searched.
|
||||
|
||||
> Warning: Verdaccio does not currently support PM2's cluster mode, running it with cluster mode may cause unknown behavior.
|
||||
> Warning: Verdaccio [does not currently support PM2's cluster mode](https://github.com/verdaccio/verdaccio/issues/1301#issuecomment-489302298), running it with cluster mode may cause unknown behavior.
|
||||
|
||||
## Publishing
|
||||
|
||||
@ -120,7 +119,7 @@ docker pull verdaccio/verdaccio
|
||||
Available as [tags](https://hub.docker.com/r/verdaccio/verdaccio/tags/).
|
||||
|
||||
```
|
||||
docker pull verdaccio/verdaccio:4.0.0
|
||||
docker pull verdaccio/verdaccio:4
|
||||
```
|
||||
|
||||
### Running verdaccio using Docker
|
||||
@ -153,6 +152,7 @@ Verdaccio aims to support all features of a standard npm client that make sense
|
||||
- Registering new users (npm adduser {newuser}) - **supported**
|
||||
- Change password (npm profile set password) - **supported**
|
||||
- Transferring ownership (npm owner add {user} {pkg}) - not supported, *PR-welcome*
|
||||
- Token (npm token) - wip [#1271](https://github.com/verdaccio/verdaccio/pull/1271)
|
||||
|
||||
### Miscellany
|
||||
|
||||
@ -162,7 +162,7 @@ Verdaccio aims to support all features of a standard npm client that make sense
|
||||
|
||||
### Security
|
||||
|
||||
- npm audit - **supported**
|
||||
- npm/yarn audit - **supported**
|
||||
|
||||
## Report a vulnerability
|
||||
|
||||
@ -182,24 +182,22 @@ You can find and chat with then over Discord, click [here](http://chat.verdaccio
|
||||
|
||||
## Who is using Verdaccio?
|
||||
|
||||
* [create-react-app](https://github.com/facebook/create-react-app/blob/master/CONTRIBUTING.md#contributing-to-e2e-end-to-end-tests) *(+64k ⭐️)*
|
||||
* [Storybook](https://github.com/storybooks/storybook) *(+34k ⭐️)*
|
||||
* [Gatsby](https://github.com/gatsbyjs/gatsby) *(+31k ⭐️)*
|
||||
* [Uppy](https://github.com/transloadit/uppy) *(+15k ⭐️)*
|
||||
* [Aurelia Framework](https://github.com/aurelia) *(+10k ⭐️)*
|
||||
* [create-react-app](https://github.com/facebook/create-react-app/blob/master/CONTRIBUTING.md#contributing-to-e2e-end-to-end-tests) *(+67k ⭐️)*
|
||||
* [Storybook](https://github.com/storybooks/storybook) *(+37k ⭐️)*
|
||||
* [Gatsby](https://github.com/gatsbyjs/gatsby) *(+34k ⭐️)*
|
||||
* [Uppy](https://github.com/transloadit/uppy) *(+19k ⭐️)*
|
||||
* [Aurelia Framework](https://github.com/aurelia) *(+11k ⭐️)*
|
||||
* [bit](https://github.com/teambit/bit) *(+6k ⭐️)*
|
||||
* [pnpm](https://github.com/pnpm/pnpm) *(+5k ⭐️)*
|
||||
* [Mozilla Neutrino](https://github.com/neutrinojs/neutrino) *(+3k ⭐️)*
|
||||
* [Amazon Web Services Cloud Development Kit](https://github.com/awslabs/aws-cdk) *(+1.8k ⭐️)*
|
||||
* [Hyperledger Composer](https://github.com/hyperledger/composer) *(+1.6k ⭐️)*
|
||||
* [webiny-js](https://github.com/Webiny/webiny-js) *(+1k ⭐️)*
|
||||
|
||||
## Special Thanks
|
||||
🤓 Don't be shy, you also can be in [the list](https://github.com/verdaccio/website/blob/master/docs/who-is-using.md).
|
||||
|
||||
Thanks to the following companies to help us to achieve our goals providing free open source licenses.
|
||||
## Sponsorship
|
||||
|
||||
[](https://www.jetbrains.com/)
|
||||
[](https://crowdin.com/)
|
||||
[](https://balsamiq.com/)
|
||||
If you are a *company/project* and you 😍 Verdaccio and FOSS, your **logo can be here** 😉 if you support our activities. [Donate](https://opencollective.com/verdaccio).
|
||||
|
||||
## Open Collective Sponsors
|
||||
|
||||
@ -222,6 +220,14 @@ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com
|
||||
|
||||
[](https://opencollective.com/verdaccio#backers)
|
||||
|
||||
## Special Thanks
|
||||
|
||||
Thanks to the following companies to help us to achieve our goals providing free open source licenses.
|
||||
|
||||
[](https://www.jetbrains.com/)
|
||||
[](https://crowdin.com/)
|
||||
[](https://balsamiq.com/)
|
||||
|
||||
## Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
@ -232,15 +238,15 @@ This project exists thanks to all the people who contribute. [[Contribute](CONTR
|
||||
|
||||
If you have any issue you can try the following options, do no desist to ask or check our issues database, perhaps someone has asked already what you are looking for.
|
||||
|
||||
* [Blog](https://medium.com/verdaccio)
|
||||
* [Blog](https://verdaccio.org/blog/)
|
||||
* [Donations](https://opencollective.com/verdaccio)
|
||||
* [Roadmaps](https://github.com/verdaccio/verdaccio/projects)
|
||||
* [Reporting an issue](https://github.com/verdaccio/verdaccio/blob/master/CONTRIBUTING.md#reporting-a-bug)
|
||||
* [Running discussions](https://github.com/verdaccio/verdaccio/issues?q=is%3Aissue+is%3Aopen+label%3Adiscuss)
|
||||
* [Chat](http://chat.verdaccio.org/)
|
||||
* [Logos](https://verdaccio.org/docs/en/logo)
|
||||
* [FAQ](https://github.com/verdaccio/verdaccio/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20)
|
||||
* [Docker Examples](https://github.com/verdaccio/docker-examples)
|
||||
* [FAQ](https://github.com/verdaccio/verdaccio/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20)
|
||||
|
||||
|
||||
### License
|
||||
|
||||
|
79
SECURITY.md
79
SECURITY.md
@ -1,30 +1,73 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
## Supported versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
The following table describes the versions of this project that are currently supported with security updates:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 2.x | :x: |
|
||||
| 3.x | :white_check_mark: |
|
||||
| 4.x | :white_check_mark: |
|
||||
| 2.x | :x: |
|
||||
| 3.x | :white_check_mark: |
|
||||
| 4.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
## Responsible disclosure security policy
|
||||
|
||||
At Verdaccio, we consider the security of our systems a top priority. But no matter how much effort we put into system security, there can still be vulnerabilities present. If you've discovered a vulnerability, please follow the guidelines below to report it to our team:
|
||||
A responsible disclosure policy helps protect users of the project from publicly disclosed security vulnerabilities without a fix by employing a process where vulnerabilities are first triaged in a private manner, and only publicly disclosed after a reasonable time period that allows patching the vulnerability and provides an upgrade path for users.
|
||||
|
||||
* Report it either [Snyk Security Team](https://snyk.io/vulnerability-disclosure/) or [npmjs Security Team](https://www.npmjs.com/advisories/report?package=verdaccio), they will be in contact with us in case of confirming the vulnerability.
|
||||
* E-mail your findings to [verdaccio@pm.me](mailto:verdaccio@pm.me). If the report contains highly sensitive information, please consider encrypting your findings using our [PGP key](https://verdaccio.nyc3.digitaloceanspaces.com/gpg/publickey.verdaccio@pm.me.asc).
|
||||
When contacting us directly via email, we will do our best efforts to respond in a reasonable time to resolve the issue. When contacting a security program their disclosure policy will provide details on timeframe, processes and paid bounties.
|
||||
|
||||
Please follow these rules when testing/reporting vulnerabilities:
|
||||
* Do not take advantage of the vulnerability you have discovered, for example by downloading more data than is necessary to demonstrate the vulnerability.
|
||||
* Do not read, modify or delete data that isn't your own.
|
||||
* We ask that you do not disclose the findings to third parties until it has been resolved.
|
||||
We kindly ask you to refrain from malicious acts that put our users, the project, or any of the project’s team members at risk.
|
||||
|
||||
What we promise:
|
||||
* We will respond to your report within 3 business days with our evaluation of the report and an expected resolution date.
|
||||
* We will keep you informed during all stages of resolving the problem.
|
||||
* To show our appreciation for your effort and cooperation during the report, we will list your name and a link to a personal website/social network profile on the page below so that the public can know you've helped keep Verdaccio secure.
|
||||
## Reporting a security issue
|
||||
|
||||
At Verdaccio, we consider the security of our systems a top priority. But no matter how much effort we put into system security, there can still be vulnerabilities present.
|
||||
|
||||
If you discover a security vulnerability, please use one of the following means of communications to report it to us:
|
||||
|
||||
* Report the security issue to the Node.js Security WG through the [HackerOne program](https://hackerone.com/nodejs-ecosystem) for ecosystem modules on npm, or to [Snyk Security Team](https://snyk.io/vulnerability-disclosure). They will help triage the security issue and work with all involved parties to remediate and release a fix.
|
||||
|
||||
Note that time-frame and processes are subject to each program’s own policy.
|
||||
|
||||
* Report the security issue to the project maintainers directly at verdaccio@pm.me. If the report contains highly sensitive information, please be advised to encrypt your findings using our [PGP key](https://verdaccio.nyc3.digitaloceanspaces.com/gpg/publickey.verdaccio@pm.me.asc) which is also available in this document.
|
||||
|
||||
Your efforts to responsibly disclose your findings are sincerely appreciated and will be taken into account to acknowledge your contributions.
|
||||
|
||||
## PGP key
|
||||
|
||||
The following is this project’s PGP key which should be used to encrypt any sensitive information shared on unsecured medium such as e-mails:
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: OpenPGP.js v4.5.1
|
||||
Comment: https://openpgpjs.org
|
||||
|
||||
xsBNBFzm3asBCACxnJDv1r6dxiM2e8iqS6B7fxY2I3X1Rc+3m8mhXOwVwRG4
|
||||
AOrQ417oSzsVLf4iocg+DWrtxzY79odTLJEovVt79rxwqIIl4y96tH+29kLB
|
||||
ao7eaYZacfstonVkBAmxBLaYv1x7cqWuukm6sBCOxapW1X9BcbR3vOghDziY
|
||||
/1AwNjupAOPvKNMtghjrdh3w0iMfZS1hw28zjM1oCeezEil+CTjgQDN+69qS
|
||||
UFG/BInJ7CVn9TvhU85inSwpxVa576fkhvFoNUrGvFvYRWtXRJndbRdBodVj
|
||||
C9At/Gb2IeNf7xqXH2KloZ1yaVNVSzLX4jqrMWeF+9Z12SjUyL6G9TwDABEB
|
||||
AAHNIXZlcmRhY2Npb0BwbS5tZSA8dmVyZGFjY2lvQHBtLm1lPsLAdQQQAQgA
|
||||
HwUCXObdqwYLCQcIAwIEFQgKAgMWAgECGQECGwMCHgEACgkQpSvoGbwFJYhn
|
||||
2wf+JF+yLQXh1EFMih6lpbx243hvglgOWmcigYVRh5mSfULcdW2pmkPQXqhE
|
||||
DW73qqwN9G9piiPnGMw7sKoB7XJVuFKyvHOYKtem5UQVRvs2rTxnSc5qFcUJ
|
||||
0w3Tw/pZ9B3fYAEYti2B/GsSOzaECfBKCFOg15xXGAdwfgff5FsorN1Gb6MG
|
||||
eCO9c8faSF/+fQUCfokwMDVzxXQFZEMx3q/rHVJ/Fm+XelZ+00c9fdyiuPW5
|
||||
dM9gATle7lz0iPtxaUDGLW8QZ/7b6O8IJ1kle0tL4AE++bXsVWxNdzhlNohH
|
||||
Hn09sIdFnG4ySTz4YJjiDd70ZdQjOGEGvutymEIN1xcNq87ATQRc5t2rAQgA
|
||||
yX2ZhUCtrz7lzK0992yveB+duVF//yo9Pei2ra9Z3GNmA+oWlRH1FTWpAmVH
|
||||
uDdUchTnxAwaKntabt3Mb1AgEZwrdiG4LuHFbdx2ls93BJ5lXdp7vB6pVf3N
|
||||
IrhHKyQ/Y5L5kMSj/GjrhO19zmj6mPPEgb3M3ZIZjQUF4pro0pExuAPA9Wxe
|
||||
awn5+0BUYFs4mZQDtTdiVuz5tWA0fNtt1aBfOPA97tmn18y4b1b0iQIJQpep
|
||||
BVVnFLeAZOevDcBJFbmQOdAjufWSSgpzX+FZ3rx6RVwwKxUiVQyUuwSQkKh5
|
||||
RufZ5zE0y7Fe/YlWXbKoj4zNJqYtjPSPngQRWf7UpwARAQABwsBfBBgBCAAJ
|
||||
BQJc5t2rAhsMAAoJEKUr6Bm8BSWIoYQH+QDw0Z84tZK4N1lh49hYyohs6vNU
|
||||
9kG69nKLQA5NymPtTxh8YOJhdJL697FkvKI4OGEO2FXUmcJS3CBJ2nBVKMq2
|
||||
1biDRKC4OhIU2RgFhS6bHy6VOn24EYs77T+zX8YXpz8ulYVln2b0QZCubN0Z
|
||||
L50tEC8HnuVMVN+/pqITdD3FjzwGZgHdW8qkKgD6qhObHCl8/cW2buCsaIAY
|
||||
eZWVPgPY1S1U0V608qYNtUCkrmUW5Sl6YLvz7JTvTsaym5mzyFXF3ErAURgI
|
||||
/v4XaWmRgNGIxbIxsFGuEs+KIKBQDJmtvJCVpBNS5IYnFf5h/LA5cfkwMKJt
|
||||
wXhyE0b/iDs60ZM=
|
||||
=QWXs
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
@ -2,4 +2,9 @@
|
||||
## we highly recommend either visit
|
||||
## https://verdaccio.org/docs/en/configuration
|
||||
## or read the local file
|
||||
## docs/config.md
|
||||
## https://github.com/verdaccio/website/tree/master/docs/config.md
|
||||
|
||||
## contribute with translations
|
||||
|
||||
## You can contribute translating documentation through the crowdin platform
|
||||
## https://crowdin.com/project/verdaccio
|
||||
|
@ -5,7 +5,7 @@ module.exports = {
|
||||
verbose: true,
|
||||
collectCoverage: true,
|
||||
testURL: 'http://localhost',
|
||||
testRegex: '(test/unit.*\\.spec|test/unit/webui/.*\\.spec)\\.js',
|
||||
testRegex: '(test/unit.*\\.spec)\\.js',
|
||||
// Some unit tests rely on data folders that look like packages. This confuses jest-hast-map
|
||||
// when it tries to scan for package.json files.
|
||||
modulePathIgnorePatterns: [
|
||||
|
15
package.json
15
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "verdaccio",
|
||||
"version": "4.0.0-beta.10",
|
||||
"version": "4.0.2",
|
||||
"description": "A lightweight private npm proxy registry",
|
||||
"author": {
|
||||
"name": "Verdaccio Maintainers",
|
||||
@ -16,18 +16,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@verdaccio/local-storage": "2.1.0",
|
||||
"@verdaccio/streams": "2.0.0",
|
||||
"@verdaccio/readme": "1.0.3",
|
||||
"@verdaccio/ui-theme": "0.1.10",
|
||||
"@verdaccio/streams": "2.0.0",
|
||||
"@verdaccio/ui-theme": "0.1.11",
|
||||
"JSONStream": "1.3.5",
|
||||
"async": "3.0.1-0",
|
||||
"async": "3.0.1",
|
||||
"body-parser": "1.19.0",
|
||||
"bunyan": "1.8.12",
|
||||
"commander": "2.20.0",
|
||||
"compression": "1.7.4",
|
||||
"cookies": "0.7.3",
|
||||
"cors": "2.8.5",
|
||||
"dayjs": "1.8.13",
|
||||
"dayjs": "1.8.14",
|
||||
"express": "4.16.4",
|
||||
"handlebars": "4.1.2",
|
||||
"http-errors": "1.7.2",
|
||||
@ -37,13 +37,13 @@
|
||||
"lodash": "4.17.11",
|
||||
"lunr-mutable-indexes": "2.3.2",
|
||||
"marked": "0.6.2",
|
||||
"mime": "2.4.2",
|
||||
"mime": "2.4.4",
|
||||
"minimatch": "3.0.4",
|
||||
"mkdirp": "0.5.1",
|
||||
"mv": "2.1.1",
|
||||
"pkginfo": "0.4.1",
|
||||
"request": "2.87.0",
|
||||
"semver": "6.0.0",
|
||||
"semver": "6.1.1",
|
||||
"verdaccio-audit": "1.2.0",
|
||||
"verdaccio-htpasswd": "2.0.0"
|
||||
},
|
||||
@ -73,6 +73,7 @@
|
||||
"jest": "24.7.1",
|
||||
"jest-environment-node": "24.7.1",
|
||||
"lint-staged": "8.1.5",
|
||||
"nock": "10.0.6",
|
||||
"prettier": "1.17.0",
|
||||
"puppeteer": "1.8.0",
|
||||
"rimraf": "2.6.3",
|
||||
|
@ -10,4 +10,4 @@ echo "Bumping version to new tag: ${lastTag}"
|
||||
echo "//$REGISTRY_URL/:_authToken=$REGISTRY_AUTH_TOKEN" > .npmrc
|
||||
|
||||
# Publish to NPM
|
||||
npm publish --tag next --registry https://$REGISTRY_URL/
|
||||
npm publish --registry https://$REGISTRY_URL/
|
||||
|
@ -8,9 +8,10 @@ import Cookies from 'cookies';
|
||||
|
||||
import { ErrorCode } from '../../../lib/utils';
|
||||
import { API_ERROR, API_MESSAGE, HTTP_STATUS } from '../../../lib/constants';
|
||||
import { createSessionToken, getApiToken, getAuthenticatedMessage, validatePassword } from '../../../lib/auth-utils';
|
||||
import { createRemoteUser, createSessionToken, getApiToken, getAuthenticatedMessage, validatePassword } from '../../../lib/auth-utils';
|
||||
import logger from '../../../lib/logger';
|
||||
|
||||
import type { Config } from '@verdaccio/types';
|
||||
import type { Config, RemoteUser } from '@verdaccio/types';
|
||||
import type { $Response, Router } from 'express';
|
||||
import type { $RequestExtend, $ResponseExtend, $NextFunctionVer, IAuth } from '../../../../types';
|
||||
|
||||
@ -22,17 +23,26 @@ export default function(route: Router, auth: IAuth, config: Config) {
|
||||
});
|
||||
});
|
||||
|
||||
route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', async function(req: $RequestExtend, res: $Response, next: $NextFunctionVer) {
|
||||
route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function(req: $RequestExtend, res: $Response, next: $NextFunctionVer) {
|
||||
const { name, password } = req.body;
|
||||
const remoteName = req.remote_user.name;
|
||||
|
||||
if (_.isNil(req.remote_user.name) === false) {
|
||||
const token = name && password ? await getApiToken(auth, config, req.remote_user, password) : undefined;
|
||||
if (_.isNil(remoteName) === false && _.isNil(name) === false && remoteName === name) {
|
||||
auth.authenticate(name, password, async function callbackAuthenticate(err, groups) {
|
||||
if (err) {
|
||||
logger.logger.trace({ name, err }, 'authenticating for user @{username} failed. Error: @{err.message}');
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD));
|
||||
}
|
||||
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
const restoredRemoteUser: RemoteUser = createRemoteUser(name, groups);
|
||||
const token = await getApiToken(auth, config, restoredRemoteUser, password);
|
||||
|
||||
return next({
|
||||
ok: getAuthenticatedMessage(req.remote_user.name),
|
||||
token,
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
|
||||
return next({
|
||||
ok: getAuthenticatedMessage(req.remote_user.name),
|
||||
token,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (validatePassword(password) === false) {
|
||||
|
@ -2,9 +2,8 @@
|
||||
* @prettier
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { addScope, addGravatarSupport, deleteProperties, sortByName, parseReadme, formatAuthor } from '../../../lib/utils';
|
||||
import { addScope, addGravatarSupport, deleteProperties, sortByName, parseReadme, formatAuthor, convertDistRemoteToLocalTarballUrls } from '../../../lib/utils';
|
||||
import { allow } from '../../middleware';
|
||||
import { DIST_TAGS, HEADER_TYPE, HEADERS, HTTP_STATUS } from '../../../lib/constants';
|
||||
import { generateGravatarUrl } from '../../../utils/user';
|
||||
@ -102,7 +101,8 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth,
|
||||
callback: function(err: Error, info: $SidebarPackage) {
|
||||
if (_.isNil(err)) {
|
||||
let sideBarInfo: any = _.clone(info);
|
||||
sideBarInfo.latest = info.versions[info[DIST_TAGS].latest];
|
||||
sideBarInfo.versions = convertDistRemoteToLocalTarballUrls(info, req, config.url_prefix).versions;
|
||||
sideBarInfo.latest = sideBarInfo.versions[info[DIST_TAGS].latest];
|
||||
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
|
||||
sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo);
|
||||
if (config.web) {
|
||||
|
@ -156,10 +156,6 @@ export const PACKAGE_ACCESS = {
|
||||
ALL: '**',
|
||||
};
|
||||
|
||||
export const UPDATE_BANNER = {
|
||||
CHANGELOG_URL: 'https://github.com/verdaccio/verdaccio/releases/tag/',
|
||||
};
|
||||
|
||||
export const STORAGE = {
|
||||
PACKAGE_FILE_NAME: 'package.json',
|
||||
FILE_EXIST_ERROR: 'EEXISTS',
|
||||
|
@ -413,13 +413,13 @@ class Storage implements IStorageHandler {
|
||||
returns callback(err, result, uplink_errors)
|
||||
*/
|
||||
_syncUplinksMetadata(name: string, packageInfo: Package, options: ISyncUplinks, callback: Callback): void {
|
||||
let exists = true;
|
||||
let found = true;
|
||||
const self = this;
|
||||
const upLinks = [];
|
||||
const hasToLookIntoUplinks = _.isNil(options.uplinksLook) || options.uplinksLook;
|
||||
|
||||
if (!packageInfo) {
|
||||
exists = false;
|
||||
found = false;
|
||||
packageInfo = generatePackageTemplate(name);
|
||||
}
|
||||
|
||||
@ -491,14 +491,36 @@ class Storage implements IStorageHandler {
|
||||
|
||||
// if we got to this point, assume that the correct package exists
|
||||
// on the uplink
|
||||
exists = true;
|
||||
found = true;
|
||||
cb();
|
||||
});
|
||||
},
|
||||
(err: Error, upLinksErrors: any) => {
|
||||
assert(!err && Array.isArray(upLinksErrors));
|
||||
if (!exists) {
|
||||
return callback(ErrorCode.getNotFound(API_ERROR.NO_PACKAGE), null, upLinksErrors);
|
||||
|
||||
// Check for connection timeout or reset errors with uplink(s)
|
||||
// (these should be handled differently from the package not being found)
|
||||
if (!found) {
|
||||
let uplinkTimeoutError;
|
||||
for (let i = 0; i < upLinksErrors.length; i++) {
|
||||
if (upLinksErrors[i]) {
|
||||
for (let j = 0; j < upLinksErrors[i].length; j++) {
|
||||
if (upLinksErrors[i][j]) {
|
||||
const code = upLinksErrors[i][j].code;
|
||||
if (code === 'ETIMEDOUT' || code === 'ESOCKETTIMEDOUT' || code === 'ECONNRESET') {
|
||||
uplinkTimeoutError = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uplinkTimeoutError) {
|
||||
return callback(ErrorCode.getServiceUnavailable(), null, upLinksErrors);
|
||||
} else {
|
||||
return callback(ErrorCode.getNotFound(API_ERROR.NO_PACKAGE), null, upLinksErrors);
|
||||
}
|
||||
}
|
||||
|
||||
if (upLinks.length === 0) {
|
||||
|
@ -551,7 +551,7 @@ class ProxyStorage implements IProxy {
|
||||
// Otherwise misconfigured proxy could return 407:
|
||||
// https://github.com/rlidwka/sinopia/issues/254
|
||||
//
|
||||
if (this.proxy === false) {
|
||||
if (!this.proxy) {
|
||||
headers['X-Forwarded-For'] = (req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'] + ', ' : '') + req.connection.remoteAddress;
|
||||
}
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
/**
|
||||
* @prettier
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import request from 'request';
|
||||
import semver from 'semver';
|
||||
import { red, green, blue, white, bold } from 'kleur';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { UPDATE_BANNER, DEFAULT_REGISTRY, HTTP_STATUS } from './constants';
|
||||
|
||||
const VERDACCIO_LATEST_REGISTRY_URL = `${DEFAULT_REGISTRY}/verdaccio/latest`;
|
||||
|
||||
/**
|
||||
* Creates NPM update banner using kleur
|
||||
*/
|
||||
export function createBanner(currentVersion: string, newVersion: string, releaseType: string): string {
|
||||
const changelog = `${UPDATE_BANNER.CHANGELOG_URL}v${newVersion}`;
|
||||
const versionUpdate = `${bold().red(currentVersion)} → ${bold().green(newVersion)}`;
|
||||
const banner = `
|
||||
${white().bold('A new ' + _.upperCase(releaseType) + ' version of Verdaccio is available. ' + versionUpdate)}
|
||||
${white().bold('Run ' + green('npm install -g verdaccio') + ' to update.')}
|
||||
${white().bold('Registry: ' + DEFAULT_REGISTRY)}
|
||||
${blue().bold('Changelog: ' + changelog)}
|
||||
`;
|
||||
return banner;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates error banner
|
||||
*/
|
||||
export function createErrorBanner(message: string): string {
|
||||
const banner = `
|
||||
${red().bold('Unable to check verdaccio version on ' + DEFAULT_REGISTRY)}
|
||||
${red().bold('Error: ' + message)}
|
||||
`;
|
||||
return banner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show verdaccio update banner on start
|
||||
*/
|
||||
export function verdaccioUpdateBanner(pkgVersion: string) {
|
||||
request(VERDACCIO_LATEST_REGISTRY_URL, function(error: ?Object = null, response: Object = {}) {
|
||||
if (!error && response.statusCode === HTTP_STATUS.OK && response.body) {
|
||||
// In case, NPM does not returns version, keeping version equals to
|
||||
// verdaccio version.
|
||||
const { version = pkgVersion } = JSON.parse(response.body);
|
||||
const releaseType = semver.diff(version, pkgVersion);
|
||||
|
||||
if (releaseType && semver.gt(version, pkgVersion)) {
|
||||
const banner = createBanner(pkgVersion, version, releaseType);
|
||||
/* eslint-disable-next-line */
|
||||
console.log(banner);
|
||||
}
|
||||
} else {
|
||||
const errorBanner = createErrorBanner(JSON.stringify(error));
|
||||
/* eslint-disable-next-line */
|
||||
console.log(errorBanner);
|
||||
}
|
||||
});
|
||||
}
|
156
test/README.md
Normal file
156
test/README.md
Normal file
@ -0,0 +1,156 @@
|
||||
## How to test Verdaccio
|
||||
|
||||
Welcome to the testing folder at Verdaccio. This document aims to help you understand how Verdaccio should be tested.
|
||||
|
||||
First of all, we should explain the testing frameworks being used. We use `jest` and other tools such as `supertest` to be able to test the API, and `puppeteer` for End-to-End testing.
|
||||
|
||||
We go along with the following rules in order to be consistent with all tests which will make your code review smooth and fast:
|
||||
|
||||
* We **type** all our tests. eg `const foo: number = 3;`
|
||||
* **Each test should be as small as possible**: You should use the `test()` block to test only one thing and do not depend on other tests. If the test requires different steps, group them with a `describe()` block.
|
||||
* All `test()` **headers titles** should begin with `test('should test ...')`: For consistency with reporting tools, this makes it easier to match the test with the feature needed to be tested.
|
||||
* **Any mock data** should be located in the `partials` folder in each section.
|
||||
* Use `yaml` for **configuration files examples** instead of JSON.
|
||||
* If you use a **file based mock storage**, it should be located in the `store` folder in each section.
|
||||
* All tests **MUST NOT** rely on external sources and must be able to run them **offline**.
|
||||
* Tests **must run on the following Operating Systems**: Unix (Mac, Linux) and Windows (7 -> latest).
|
||||
* If you are creating mock data file which use the state and need a clean state, use `rimraf` to remove folders.
|
||||
|
||||
## Testing sections
|
||||
|
||||
Verdaccio testing is split in 3 sections, each of them has different setup and scope. The most important is the **unit test**. All sections have custom **jest configuration files**.
|
||||
|
||||
If you are adding new tests, comply with the following:
|
||||
|
||||
* If you add a new API endpoint, unit and functional tests are mandatory.
|
||||
* If you add a utility, unit test is mandatory.
|
||||
* If you are adding a new web API endpoint, the unit test, functional test and if such endpoint has new changes in the UI, E2E test is also mandatory.
|
||||
* If you add or refactor a core class, unit test is mandatory.
|
||||
* If you fix a bug, you **must** add a new `test()` block to prove that the patch fixes the bug.
|
||||
|
||||
### Unit test
|
||||
|
||||
Unit tests aim to test the CLI API and the Web API. The configuration file is located at `jest.config.js`.
|
||||
|
||||
> Unit testing does not need require pre-compile code, jest will catch any change done to the `{root}/src` files.
|
||||
|
||||
#### Testing an endpoint
|
||||
|
||||
We have prepared a template at `test/unit/api/api.__test.template.spec.js` that you can follow to create your own unit test. Only the tests are appended with `.spec.js` which will be found and used by `jest`.
|
||||
|
||||
> Feel free to suggest improvements to the template, there is still a lot of room for improvement.
|
||||
|
||||
We recommend the following approach when you create a unit test:
|
||||
|
||||
* For new utilities, we recommend creating a new spec.
|
||||
* For existing utilities, if the method is already being tested, just add a new `test()` block.
|
||||
* Notice that all API spec files are appended with `api.[feature].spec.js`, we recommend to follow the same approach. eg: `api.[deprecate].spec.js`.
|
||||
* Don't mix utilities with API tests.
|
||||
|
||||
### Functional tests
|
||||
|
||||
The functional tests aim to run only **cli endpoint** and **web point** using real request to an existing and compiled running Verdaccio server.
|
||||
|
||||
> Be aware if you change something in the `{root}/src` source code, you must run `yarn code:build` before to be able to see your changes because functional tests use the transpiled code.
|
||||
|
||||
All tests must be included in the `test/functional/index.spec.js` file, which bootstraps the whole process. There is only one spec file and **must be only one**.
|
||||
|
||||
The jest configuration file is defined in `test/jest.config.functional.js`. The configuration will create a custom environment launching 3 Verdaccio servers with different configurations.
|
||||
|
||||
The servers are linked as follows:
|
||||
|
||||
* Server 1
|
||||
* -> Server 2
|
||||
* -> Server 3
|
||||
* Server 2
|
||||
* -> Server 1
|
||||
* Server 3
|
||||
* -> Server 2
|
||||
* -> Server 1
|
||||
* Express app: (if you need to emulate any external endpoint, use the express app)
|
||||
|
||||
Server 1 runs on port `55551`, Server 2 on port `55552` and Server 3 on port `55553`.
|
||||
|
||||
> If you have the need to increase the number of servers running, it is possible, but please discuss with the team before you go in that path.
|
||||
|
||||
|
||||
#### Adding a new block
|
||||
|
||||
To add a new feature you need to export the feature as a function that take as an argument any of the servers you want to interact.
|
||||
|
||||
|
||||
```js
|
||||
// newFeature.js
|
||||
|
||||
export default function(server) {
|
||||
|
||||
describe('package access control', () => {
|
||||
test('should ...', (done) => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Then import the feature and run the function within the main `describe` block.
|
||||
|
||||
```js
|
||||
// index.spec.js
|
||||
|
||||
import newFeature from './newFeature';
|
||||
|
||||
describe('functional test verdaccio', function() {
|
||||
// test are fast, but do not change this time out, 10 seconds should be more than enough
|
||||
jest.setTimeout(10000);
|
||||
// servers are accessed via a global jest state.
|
||||
const server1: IServerBridge = global.__SERVERS__[0];
|
||||
const server2: IServerBridge = global.__SERVERS__[1];
|
||||
const server3: IServerBridge = global.__SERVERS__[2];
|
||||
const app = global.__WEB_SERVER__.app;
|
||||
|
||||
// include as much servers you need
|
||||
newFeature(server1, server2, server3);
|
||||
});
|
||||
```
|
||||
|
||||
Functional tests run over one single file, thus, it is not possible at this stage to run tests individually.
|
||||
|
||||
### E2E Test
|
||||
|
||||
Verdaccio includes a Web User Interface that must be tested. We use End-to-End testing to run some smock tests against the web API using the UI Theme
|
||||
include by default.
|
||||
|
||||
```bash
|
||||
yarn lint && yarn test:all
|
||||
```
|
||||
|
||||
The test does not have aim to test the integrity of the page, mostly, ensure the basic functionality still works. If you add or modify
|
||||
a UI feature, the tests must be updated.
|
||||
|
||||
> The tests rely on CSS classes naming convention, so, it is required some sort of coordination with the **verdaccio/ui** project.
|
||||
|
||||
We uses `puppeteer`, you can find more information about how to use it in their website.
|
||||
|
||||
## Before commit
|
||||
|
||||
We recommend run your tests and linters before commit.
|
||||
|
||||
```bash
|
||||
yarn lint && yarn test:all
|
||||
```
|
||||
|
||||
|
||||
You can find more in our [guide about run and debugging test](https://github.com/verdaccio/verdaccio/wiki/Running-and-Debugging-tests#running-the-test).
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
Verdaccio uses [CircleCI](https://circleci.com/gh/verdaccio) as its primary Continuous Integration tool. We run the tests against the most common Node.js versions available. Among them is LTS and the latest release. Before the PR is being merged, all checks must be green.
|
||||
Node.js versions available, LTS and the latest release. Before the PR is being merged, all check must be green.
|
||||
|
||||
> You need a CircleCI account to be able see the test running
|
||||
|
||||
|
||||
|
||||
|
||||
|
21
test/functional/fixtures/plugins/middlewares.uplink.js
Normal file
21
test/functional/fixtures/plugins/middlewares.uplink.js
Normal file
@ -0,0 +1,21 @@
|
||||
const nock = require('nock');
|
||||
|
||||
function Plugin(config) {
|
||||
const self = Object.create(Plugin.prototype);
|
||||
self._config = config;
|
||||
return self;
|
||||
}
|
||||
|
||||
Plugin.prototype.register_middlewares = function (app, auth, storage) {
|
||||
|
||||
app.get('/test-uplink-timeout-*', function (req, res, next) {
|
||||
nock('http://localhost:55552')
|
||||
.get(req.path)
|
||||
.socketDelay(31000).reply(200); // 31s is greater than the default 30s connection timeout
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports = Plugin;
|
@ -28,6 +28,7 @@ import race from './performance/race';
|
||||
import pluginsAuth from './plugins/auth';
|
||||
import middleware from './plugins/middleware';
|
||||
import upLinkCache from './uplinks/cache';
|
||||
import uplinkTimeout from './uplinks/timeout';
|
||||
|
||||
describe('functional test verdaccio', function() {
|
||||
jest.setTimeout(10000);
|
||||
@ -54,14 +55,15 @@ describe('functional test verdaccio', function() {
|
||||
security(server1);
|
||||
addtag(server1);
|
||||
pluginsAuth(server2);
|
||||
notify(app);
|
||||
notify(app);
|
||||
uplinkTimeout(server1, server2, server3);
|
||||
// requires packages published to server1/server2
|
||||
upLinkCache(server1, server2, server3);
|
||||
adduser(server1);
|
||||
logout(server1);
|
||||
basic(server1, server2);
|
||||
simpleSearch(server1, server2, app)
|
||||
|
||||
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', function(err) {
|
||||
|
@ -6,6 +6,10 @@ web:
|
||||
enable: true
|
||||
title: verdaccio-server-1
|
||||
|
||||
middlewares:
|
||||
../fixtures/plugins/middlewares.uplink:
|
||||
message: provides uplink mocking (e.g. simulates socket timeout)
|
||||
|
||||
auth:
|
||||
auth-memory:
|
||||
users:
|
||||
@ -116,6 +120,12 @@ packages:
|
||||
publish: $authenticated
|
||||
storage: sub_storage
|
||||
|
||||
'test-uplink-timeout-*':
|
||||
access: $all
|
||||
proxy:
|
||||
- server2
|
||||
- server3
|
||||
|
||||
'*':
|
||||
access: test $anonymous
|
||||
publish: test $anonymous
|
||||
|
@ -35,6 +35,10 @@ packages:
|
||||
access: $all
|
||||
proxy: server2
|
||||
|
||||
'test-uplink-timeout-*':
|
||||
access: $all
|
||||
publish: $all
|
||||
|
||||
'*':
|
||||
access: $all
|
||||
|
||||
|
27
test/functional/uplinks/timeout.js
Normal file
27
test/functional/uplinks/timeout.js
Normal file
@ -0,0 +1,27 @@
|
||||
import {HTTP_STATUS} from "../../../src/lib/constants";
|
||||
|
||||
const PKG_SINGLE_UPLINK = 'test-uplink-timeout-single';
|
||||
const PKG_MULTIPLE_UPLINKS = 'test-uplink-timeout-multiple';
|
||||
|
||||
export default function (server, server2, server3) {
|
||||
|
||||
describe('uplink connection timeouts', () => {
|
||||
beforeAll(async () => {
|
||||
await server2.addPackage(PKG_SINGLE_UPLINK).status(HTTP_STATUS.CREATED);
|
||||
await server2.addPackage(PKG_MULTIPLE_UPLINKS).status(HTTP_STATUS.CREATED);
|
||||
await server3.addPackage(PKG_MULTIPLE_UPLINKS).status(HTTP_STATUS.CREATED);
|
||||
});
|
||||
|
||||
describe('get package', () => {
|
||||
test('503 response when uplink connection ESOCKETTIMEDOUT', () => {
|
||||
return server.getPackage(PKG_SINGLE_UPLINK).status(HTTP_STATUS.SERVICE_UNAVAILABLE);
|
||||
});
|
||||
|
||||
test('200 response even though one uplink timesout', () => {
|
||||
return server.getPackage(PKG_MULTIPLE_UPLINKS).status(HTTP_STATUS.OK)
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
@ -1,6 +1,15 @@
|
||||
// @flow
|
||||
|
||||
import {HEADER_TYPE, HEADERS, HTTP_STATUS} from '../../../src/lib/constants';
|
||||
import {HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BEARER} from '../../../src/lib/constants';
|
||||
import {buildToken} from "../../../src/lib/utils";
|
||||
|
||||
// API Helpers
|
||||
|
||||
// This file should contain utilities to avoid repeated task over API unit testing,
|
||||
// Please, comply with the following:
|
||||
// - Promisify everything
|
||||
// - Encourage using constants or create new ones if it's needed
|
||||
// - // $FlowFixMe or any is fine if there is no other way
|
||||
|
||||
export function getPackage(
|
||||
request: any,
|
||||
@ -19,6 +28,24 @@ export function getPackage(
|
||||
});
|
||||
}
|
||||
|
||||
export function loginUserToken(request: any,
|
||||
user: string,
|
||||
credentials: any,
|
||||
token: string,
|
||||
statusCode: number = HTTP_STATUS.CREATED) {
|
||||
// $FlowFixMe
|
||||
return new Promise((resolve) => {
|
||||
request.put(`/-/user/org.couchdb.user:${user}`)
|
||||
.send(credentials)
|
||||
.set('authorization', buildToken(TOKEN_BEARER, token))
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(statusCode)
|
||||
.end(function(err, res) {
|
||||
return resolve([err, res]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function addUser(request: any, user: string, credentials: any,
|
||||
statusCode: number = HTTP_STATUS.CREATED) {
|
||||
// $FlowFixMe
|
||||
@ -50,7 +77,7 @@ export function getProfile(request: any, token: string, statusCode: number = HTT
|
||||
// $FlowFixMe
|
||||
return new Promise((resolve) => {
|
||||
request.get(`/-/npm/v1/user`)
|
||||
.set(HEADERS.AUTHORIZATION, `Bearer ${token}`)
|
||||
.set('authorization', buildToken(TOKEN_BEARER, token))
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(statusCode)
|
||||
.end(function(err, res) {
|
||||
|
@ -7,12 +7,12 @@ import rimraf from 'rimraf';
|
||||
|
||||
import endPointAPI from '../../../../src/api';
|
||||
|
||||
import {HEADERS, HTTP_STATUS, HEADER_TYPE, TOKEN_BEARER, TOKEN_BASIC} from '../../../../src/lib/constants';
|
||||
import {HEADERS, HTTP_STATUS, HEADER_TYPE, TOKEN_BEARER, TOKEN_BASIC, API_ERROR} from '../../../../src/lib/constants';
|
||||
import {mockServer} from '../../__helper/mock';
|
||||
import {DOMAIN_SERVERS} from '../../../functional/config.functional';
|
||||
import {buildToken, parseConfigFile} from '../../../../src/lib/utils';
|
||||
import {parseConfigurationFile} from '../../__helper';
|
||||
import {addUser, getPackage} from '../../__helper/api';
|
||||
import {addUser, getPackage, loginUserToken} from '../../__helper/api';
|
||||
import {setup} from '../../../../src/lib/logger';
|
||||
import {buildUserBuffer} from '../../../../src/lib/auth-utils';
|
||||
|
||||
@ -67,9 +67,11 @@ describe('endpoint user auth JWT unit test', () => {
|
||||
expect(err).toBeNull();
|
||||
expect(res.body.ok).toBeDefined();
|
||||
expect(res.body.token).toBeDefined();
|
||||
const token = res.body.token;
|
||||
|
||||
const { token } = res.body;
|
||||
expect(typeof token).toBe('string');
|
||||
expect(res.body.ok).toMatch(`user '${credentials.name}' created`);
|
||||
|
||||
// testing JWT auth headers with token
|
||||
// we need it here, because token is required
|
||||
const [err1, resp1] = await getPackage(request(app), buildToken(TOKEN_BEARER, token), 'vue');
|
||||
@ -90,6 +92,7 @@ describe('endpoint user auth JWT unit test', () => {
|
||||
await addUser(request(app), credentials.name, credentials);
|
||||
// it should fails conflict 409
|
||||
await addUser(request(app), credentials.name, credentials, HTTP_STATUS.CONFLICT);
|
||||
|
||||
// npm will try to sign in sending credentials via basic auth header
|
||||
const token = buildUserBuffer(credentials.name, credentials.password).toString('base64');
|
||||
request(app).put(`/-/user/org.couchdb.user:${credentials.name}/-rev/undefined`)
|
||||
@ -101,6 +104,7 @@ describe('endpoint user auth JWT unit test', () => {
|
||||
expect(err).toBeNull();
|
||||
expect(res.body.ok).toBeDefined();
|
||||
expect(res.body.token).toBeDefined();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
@ -113,4 +117,24 @@ describe('endpoint user auth JWT unit test', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
test('should fails on login if user credentials are invalid even if jwt valid token is provided', async (done) => {
|
||||
const credentials = { name: 'newFailsUser', password: 'secretPass' };
|
||||
const [err, res] = await addUser(request(app), credentials.name, credentials);
|
||||
expect(err).toBeNull();
|
||||
expect(res.body.ok).toBeDefined();
|
||||
expect(res.body.token).toBeDefined();
|
||||
|
||||
const { token } = res.body;
|
||||
expect(typeof token).toBe('string');
|
||||
expect(res.body.ok).toMatch(`user '${credentials.name}' created`);
|
||||
|
||||
// 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);
|
||||
expect(err2).toBeNull();
|
||||
expect(resp2.statusCode).toBe(HTTP_STATUS.UNAUTHORIZED);
|
||||
expect(resp2.body.error).toMatch(API_ERROR.BAD_USERNAME_PASSWORD);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
94
test/unit/modules/utils/api.__test.template.spec.js
Normal file
94
test/unit/modules/utils/api.__test.template.spec.js
Normal file
@ -0,0 +1,94 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* PLEASE DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This test is just for teaching purpose, use this example as template for your new endpoint API unit test
|
||||
*
|
||||
* If you have any questions, ask at the http://chat.verdaccio.org #questions channel.
|
||||
*
|
||||
*/
|
||||
import request from 'supertest';
|
||||
import _ from 'lodash';
|
||||
import path from 'path';
|
||||
import rimraf from 'rimraf';
|
||||
|
||||
import endPointAPI from '../../../../src/api/index';
|
||||
import {mockServer} from '../../__helper/mock';
|
||||
import {DOMAIN_SERVERS} from '../../../functional/config.functional';
|
||||
import {parseConfigFile} from '../../../../src/lib/utils';
|
||||
import {parseConfigurationFile} from '../../__helper';
|
||||
import {addUser} from '../../__helper/api';
|
||||
import {setup} from '../../../../src/lib/logger';
|
||||
|
||||
// we must start logging without output
|
||||
setup([]);
|
||||
|
||||
const parseConfigurationJWTFile = () => {
|
||||
// Any new test must have a custom yaml file, try to name it based on the feature, the config
|
||||
// file does not need to include all configuration, just the part is needs
|
||||
// eg: test/unit/partials/config/yaml/api-jwt/jwt.yaml
|
||||
return parseConfigurationFile(`api-jwt/jwt`);
|
||||
};
|
||||
|
||||
describe('endpoint example unit test', () => {
|
||||
let app;
|
||||
let mockRegistry;
|
||||
|
||||
beforeAll(function(done) {
|
||||
// 1. We create a route for a custom storage folder for this test
|
||||
const store = path.join(__dirname, '../partials/store/test-jwt-storage');
|
||||
// 2. The port must be unique (at this point this is not automated, need to be checked manually)
|
||||
const mockServerPort = 55546;
|
||||
// 3. Use rimraf to clean the state each time you run the test
|
||||
rimraf(store, async () => {
|
||||
// 4. Use a custom configuration file
|
||||
const confS = parseConfigFile(parseConfigurationJWTFile());
|
||||
// 5. Customise specific properties
|
||||
const configForTest = _.assign({}, _.cloneDeep(confS), {
|
||||
storage: store,
|
||||
uplinks: {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
},
|
||||
// 6. The self_path is important be the same as the store
|
||||
self_path: store,
|
||||
// 7. Define the location of the .htpasswd file, this is relative to self_path.
|
||||
auth: {
|
||||
htpasswd: {
|
||||
file: './test-jwt-storage/.htpasswd'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 8. Use the helper `endPointAPI` to mock the API
|
||||
app = await endPointAPI(configForTest);
|
||||
// 9 . Use `mockServer` to mock launch the server.
|
||||
mockRegistry = await mockServer(mockServerPort).init();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(function(done) {
|
||||
// 10. Do not forget to stop the API, or it will run forever.
|
||||
mockRegistry[0].stop();
|
||||
done();
|
||||
});
|
||||
|
||||
test('should test add a new user with JWT enabled', async (done) => {
|
||||
// At this point the server is running and you can run the test
|
||||
|
||||
const credentials = { name: 'JotaJWT', password: 'secretPass' };
|
||||
// 11. Use helpers for repetitive tasks
|
||||
const [err, res] = await addUser(request(app), credentials.name, credentials);
|
||||
|
||||
// 12. test your output
|
||||
expect(err).toBeNull();
|
||||
expect(res.body.ok).toBeDefined();
|
||||
expect(res.body.token).toBeDefined();
|
||||
|
||||
// 13. end the async test
|
||||
done();
|
||||
});
|
||||
});
|
BIN
yarn.lock
BIN
yarn.lock
Binary file not shown.
Loading…
Reference in New Issue
Block a user