Skip to content

Commit 4765a9a

Browse files
rtsaoarcanis
authored andcommitted
Fix missing credentials when fetching tarballs (#622)
* Add support for absolute paths in npmHttpUtils.get * Use npmHttpUtils.get in NpmHttpFetcher * Add regression test * Add additional regression test * Add yet another regression test
1 parent 18aa061 commit 4765a9a

File tree

8 files changed

+99
-5
lines changed

8 files changed

+99
-5
lines changed

packages/acceptance-tests/pkg-tests-core/sources/utils/tests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ export const startPackageServer = (): Promise<string> => {
233233
[version as string]: Object.assign({}, packageVersionEntry!.packageJson, {
234234
dist: {
235235
shasum: await getPackageArchiveHash(name, version),
236-
tarball: localName === `unconventional-tarball`
236+
tarball: (localName === `unconventional-tarball` || localName === `private-unconventional-tarball`)
237237
? (await getPackageHttpArchivePath(name, version)).replace(`/-/`, `/tralala/`)
238238
: await getPackageHttpArchivePath(name, version),
239239
},
@@ -377,7 +377,7 @@ export const startPackageServer = (): Promise<string> => {
377377
} else if (match = url.match(/^\/(?:(@[^\/]+)\/)?([^@\/][^\/]*)\/(-|tralala)\/\2-(.*)\.tgz$/)) {
378378
const [, scope, localName, split, version] = match;
379379

380-
if (localName === `unconventional-tarball` && split === `-`)
380+
if ((localName === `unconventional-tarball` || localName === `private-unconventional-tarball`) && split === `-`)
381381
return null;
382382

383383
return {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* @flow */
2+
3+
module.exports = require(`./package.json`);
4+
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "@private/unconventional-tarball",
3+
"version": "1.0.0"
4+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* @flow */
2+
3+
module.exports = require(`./package.json`);
4+
5+
for (const key of [`dependencies`, `devDependencies`, `peerDependencies`]) {
6+
for (const dep of Object.keys(module.exports[key] || {})) {
7+
// $FlowFixMe The whole point of this file is to be dynamic
8+
module.exports[key][dep] = require(dep);
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "private-unconventional-tarball",
3+
"version": "1.0.0"
4+
}

packages/acceptance-tests/pkg-tests-specs/sources/auth.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,63 @@ describe(`Auth tests`, () => {
155155
),
156156
);
157157

158+
test(
159+
`it should install unconventional scoped packages which require authentication if an authentication token is configured`,
160+
makeTemporaryEnv(
161+
{
162+
dependencies: {[`@private/unconventional-tarball`]: `1.0.0`},
163+
},
164+
async ({path, run, source}) => {
165+
await writeFile(`${path}/.yarnrc.yml`, `npmAuthToken: "${AUTH_TOKEN}"\n`);
166+
167+
await run(`install`);
168+
169+
await expect(source(`require('@private/unconventional-tarball')`)).resolves.toMatchObject({
170+
name: `@private/unconventional-tarball`,
171+
version: `1.0.0`,
172+
});
173+
},
174+
),
175+
);
176+
177+
test(
178+
`it should install unconventional scoped packages which require authentication if npmAlwaysAuth is set to true and an authentication ident is present`,
179+
makeTemporaryEnv(
180+
{
181+
dependencies: {[`@private/unconventional-tarball`]: `1.0.0`},
182+
},
183+
async ({path, run, source}) => {
184+
await writeFile(`${path}/.yarnrc.yml`, `npmAuthIdent: "${AUTH_IDENT}"\nnpmAlwaysAuth: true\n`);
185+
186+
await run(`install`);
187+
188+
await expect(source(`require('@private/unconventional-tarball')`)).resolves.toMatchObject({
189+
name: `@private/unconventional-tarball`,
190+
version: `1.0.0`,
191+
});
192+
},
193+
),
194+
);
195+
196+
test(
197+
`it should install unconventional unscoped packages which require authentication if npmAlwaysAuth is set to true and an authentication ident is present`,
198+
makeTemporaryEnv(
199+
{
200+
dependencies: {[`private-unconventional-tarball`]: `1.0.0`},
201+
},
202+
async ({path, run, source}) => {
203+
await writeFile(`${path}/.yarnrc.yml`, `npmAuthIdent: "${AUTH_IDENT}"\nnpmAlwaysAuth: true\n`);
204+
205+
await run(`install`);
206+
207+
await expect(source(`require('private-unconventional-tarball')`)).resolves.toMatchObject({
208+
name: `private-unconventional-tarball`,
209+
version: `1.0.0`,
210+
});
211+
},
212+
),
213+
);
214+
158215
test(
159216
`it should fail when an invalid authenticaation token is used`,
160217
makeTemporaryEnv(

packages/plugin-npm/sources/NpmHttpFetcher.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import {Fetcher, FetchOptions, MinimalFetchOptions} from '@yarnpkg/core';
22
import {Locator, MessageName} from '@yarnpkg/core';
3-
import {httpUtils, structUtils, tgzUtils} from '@yarnpkg/core';
3+
import {structUtils, tgzUtils} from '@yarnpkg/core';
44
import semver from 'semver';
55
import {URL} from 'url';
66

77
import {PROTOCOL} from './constants';
8+
import * as npmHttpUtils from './npmHttpUtils';
89

910
export class NpmHttpFetcher implements Fetcher {
1011
supports(locator: Locator, opts: MinimalFetchOptions) {
@@ -50,8 +51,9 @@ export class NpmHttpFetcher implements Fetcher {
5051
if (archiveUrl === null)
5152
throw new Error(`Assertion failed: The archiveUrl querystring parameter should have been available`);
5253

53-
const sourceBuffer = await httpUtils.get(archiveUrl, {
54+
const sourceBuffer = await npmHttpUtils.get(archiveUrl, {
5455
configuration: opts.project.configuration,
56+
ident: locator,
5557
});
5658

5759
return await tgzUtils.convertToZip(sourceBuffer, {

packages/plugin-npm/sources/npmHttpUtils.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,14 @@ export async function get(path: string, {configuration, headers, ident, authType
4747
if (auth)
4848
headers = {...headers, authorization: auth};
4949

50-
return await httpUtils.get(registry + path, {configuration, headers, ...rest});
50+
let url;
51+
try {
52+
url = new URL(path);
53+
} catch (e) {
54+
url = new URL(registry + path);
55+
}
56+
57+
return await httpUtils.get(url.href, {configuration, headers, ...rest});
5158
}
5259

5360
export async function put(path: string, body: httpUtils.Body, {configuration, headers, ident, authType = AuthType.ALWAYS_AUTH, registry, ...rest}: Options) {

0 commit comments

Comments
 (0)