-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix scoped pkg auth when using npm private pkgs via npm login --scope #5162
Changes from all commits
a05fc91
93dd2ab
9dcbc8f
ea3fba0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,48 +99,21 @@ export default class NpmRegistry extends Registry { | |
} | ||
} | ||
|
||
isRequestToRegistry(requestUrl: string, registryUrl: string): boolean { | ||
const normalizedRequestUrl = normalizeUrl(requestUrl); | ||
const normalizedRegistryUrl = normalizeUrl(registryUrl); | ||
const requestParsed = url.parse(normalizedRequestUrl); | ||
const registryParsed = url.parse(normalizedRegistryUrl); | ||
const requestHost = requestParsed.host || ''; | ||
const registryHost = registryParsed.host || ''; | ||
const requestPath = requestParsed.path || ''; | ||
const registryPath = registryParsed.path || ''; | ||
const customHostSuffix = this.getRegistryOrGlobalOption(registryUrl, 'custom-host-suffix'); | ||
|
||
return ( | ||
requestHost === registryHost && | ||
(requestPath.startsWith(registryPath) || | ||
// For some registries, the package path does not prefix with the registry path | ||
(typeof customHostSuffix === 'string' && requestHost.endsWith(customHostSuffix))) | ||
); | ||
} | ||
|
||
request(pathname: string, opts?: RegistryRequestOptions = {}, packageName: ?string): Promise<*> { | ||
// packageName needs to be escaped when if it is passed | ||
const packageIdent = (packageName && NpmRegistry.escapeName(packageName)) || pathname; | ||
const registry = this.getRegistry(packageIdent); | ||
const requestUrl = this.getRequestUrl(registry, pathname); | ||
|
||
const alwaysAuth = this.getRegistryOrGlobalOption(registry, 'always-auth'); | ||
|
||
const headers = Object.assign( | ||
{ | ||
Accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*', | ||
}, | ||
opts.headers, | ||
); | ||
|
||
const isToRegistry = this.isRequestToRegistry(requestUrl, registry); | ||
|
||
// this.token must be checked to account for publish requests on non-scopped packages | ||
if (this.token || (isToRegistry && (alwaysAuth || this.isScopedPackage(packageIdent)))) { | ||
const authorization = this.getAuth(packageIdent); | ||
if (authorization) { | ||
headers.authorization = authorization; | ||
} | ||
const authorization = this.getAuth(packageIdent); | ||
if (authorization) { | ||
headers.authorization = authorization; | ||
} | ||
|
||
return this.requestManager.request({ | ||
|
@@ -271,6 +244,7 @@ export default class NpmRegistry extends Registry { | |
if (registry) { | ||
return String(registry); | ||
} | ||
return ''; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to make sure that if URL is with a protocol, e.g. |
||
} | ||
|
||
for (const scope of [this.getScope(packageIdent), '']) { | ||
|
@@ -285,15 +259,41 @@ export default class NpmRegistry extends Registry { | |
} | ||
|
||
getAuth(packageIdent: string): string { | ||
// this.token must be checked to account for publish requests on non-scopped packages | ||
if (this.token) { | ||
return this.token; | ||
} | ||
|
||
const baseRegistry = this.getRegistry(packageIdent); | ||
const registries = [baseRegistry]; | ||
let registry = this.getRegistry(packageIdent); | ||
|
||
// Support for an existing feature: custom-host-suffix | ||
// When custom-host-suffix global option is set, and request url matches | ||
// this custom-host-suffix, we extract scope from the URL. We then use | ||
// this scope to determine which auth token to use for that scope | ||
if (packageIdent.match(REGEX_REGISTRY_PREFIX)) { | ||
const customHostSuffix = this.getRegistryOrGlobalOption(registry || DEFAULT_REGISTRY, 'custom-host-suffix'); | ||
if (typeof customHostSuffix === 'string') { | ||
const requestHost = url.parse(normalizeUrl(packageIdent)).host || ''; | ||
if (requestHost.endsWith(customHostSuffix)) { | ||
const scope = this.getScope(packageIdent); | ||
registry = this.getRegistry(scope + '/pkg'); | ||
} | ||
} | ||
} | ||
|
||
if (!registry) { | ||
return ''; | ||
} | ||
|
||
const alwaysAuth = this.getRegistryOrGlobalOption(registry, 'always-auth'); | ||
if (!alwaysAuth && !this.isScopedPackage(packageIdent)) { | ||
return ''; | ||
} | ||
|
||
const registries = [registry]; | ||
|
||
// If sending a request to the Yarn registry, we must also send it the auth token for the npm registry | ||
if (baseRegistry === YARN_REGISTRY) { | ||
if (registry === YARN_REGISTRY) { | ||
registries.push(DEFAULT_REGISTRY); | ||
} | ||
|
||
|
@@ -346,4 +346,12 @@ export default class NpmRegistry extends Registry { | |
getRegistryOrGlobalOption(registry: string, option: string): mixed { | ||
return this.getRegistryOption(registry, option) || this.getOption(option); | ||
} | ||
|
||
getAvailableRegistries(): Array<string> { | ||
const availableRegistries = super.getAvailableRegistries(); | ||
if (availableRegistries.indexOf(DEFAULT_REGISTRY) === -1) { | ||
availableRegistries.push(DEFAULT_REGISTRY); | ||
} | ||
return availableRegistries; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In theory only |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By default,
npm login
populates the.npmrc
file with the full url, e.g.and not
I made sure this is not a regression by editing away the
https://
in my~/.npmrc
and runningnpm install
which gives menpm ERR! Only absolute URLs are supported