Skip to content

Commit

Permalink
feat(auth): Add basic auth support for pathed registries (#5322)
Browse files Browse the repository at this point in the history
  • Loading branch information
KidkArolis authored and Gudahtt committed Oct 6, 2018
1 parent 1b78b1a commit 9bb2cfb
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Expand Up @@ -4,7 +4,9 @@ Please add one entry in this file for each change in Yarn's behavior. Use the sa

## Master

*Nothing yet*
- Adds support for basic auth for registries with paths, such as artifactory

[#5322](https://github.com/yarnpkg/yarn/pull/5322) - [**Karolis Narkevicius**](https://twitter.com/KidkArolis)

## 1.12.0

Expand Down
51 changes: 50 additions & 1 deletion __tests__/registries/npm-registry.js
Expand Up @@ -6,6 +6,11 @@ import NpmRegistry from '../../src/registries/npm-registry.js';
import {BufferReporter} from '../../src/reporters/index.js';
import homeDir, {home} from '../../src/util/user-home-dir.js';

function basicAuth(username, password): string {
const pw = Buffer.from(String(password), 'base64').toString();
return Buffer.from(String(username) + ':' + pw).toString('base64');
}

describe('normalizeConfig', () => {
beforeAll(() => {
process.env.REPLACE = 'REPLACED';
Expand Down Expand Up @@ -554,6 +559,46 @@ describe('request', () => {
},
],
},
{
title: 'using username/password config for registries where pathnames play a role',
config: {
'@private:registry': 'https://registry.myorg.com/api/npm/registry/',
'//registry.myorg.com/api/npm/registry/:username': 'scopedPrivateUsername',
'//registry.myorg.com/api/npm/registry/:_password': 'scopedPrivatePassword',
'//registry.myorg.com/api/packages/:username': 'scopedPrivateUsername',
'//registry.myorg.com/api/packages/:_password': 'scopedPrivatePassword',
},
requests: [
{
url: '@private/pkg',
pkg: '@private/pkg',
expect: {
root: 'https://registry.myorg.com/api/npm/registry/',
auth: basicAuth('scopedPrivateUsername', 'scopedPrivatePassword'),
basicAuth: true,
},
},
{
url: 'https://some.cdn.com/some-hash/@private-pkg-1.0.0.tar.gz',
pkg: '@private/pkg',
expect: {root: 'https://some.cdn.com', auth: false},
},
{
url: 'https://some.cdn.com/@private/pkg',
pkg: null,
expect: {root: 'https://some.cdn.com', auth: false},
},
{
url: 'https://registry.myorg.com/api/packages/private---pkg.tar.gz',
pkg: '@private/pkg',
expect: {
root: 'https://registry.myorg.com/api/packages/',
auth: basicAuth('scopedPrivateUsername', 'scopedPrivatePassword'),
basicAuth: true,
},
},
],
},
];

testCases.forEach(testCase => {
Expand All @@ -566,7 +611,11 @@ describe('request', () => {
(req.skip ? it.skip : req.only ? it.only : it)(desc, () => {
const requestParams = registry.request(req.url, {}, req.pkg);
expect(requestParams.url.substr(0, req.expect.root.length)).toBe(req.expect.root);
expect(requestParams.headers.authorization).toBe(req.expect.auth ? `Bearer ${req.expect.auth}` : undefined);
if (req.expect.basicAuth) {
expect(requestParams.headers.authorization).toBe(req.expect.auth ? `Basic ${req.expect.auth}` : undefined);
} else {
expect(requestParams.headers.authorization).toBe(req.expect.auth ? `Bearer ${req.expect.auth}` : undefined);
}
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion src/registries/npm-registry.js
Expand Up @@ -179,7 +179,7 @@ export default class NpmRegistry extends Registry {
const requestParts = urlParts(requestUrl);
return !!Object.keys(config).find(option => {
const parts = option.split(':');
if (parts.length === 2 && parts[1] === '_authToken') {
if ((parts.length === 2 && parts[1] === '_authToken') || parts[1] === '_password') {
const registryParts = urlParts(parts[0]);
if (requestParts.host === registryParts.host && requestParts.path.startsWith(registryParts.path)) {
return true;
Expand Down

0 comments on commit 9bb2cfb

Please sign in to comment.