@@ -21,6 +21,15 @@ Supported SRC_URI options are:
- destsuffix
Specifies the directory to use to unpack the package (default: npm).
+
+- namespace
+ The npm namespace name (without the preceding "@").
+
+- username
+ Specifies the basic auth username to use when accessing the npm registry.
+
+- password
+ Specifies the basic auth password (or API key) to use when accessing the npm registry.
"""
import base64
@@ -82,6 +91,33 @@ def npm_unpack(tarball, destdir, d):
runfetchcmd(cmd, d, workdir=destdir)
runfetchcmd("chmod -R +X '%s'" % (destdir), d, quiet=True, workdir=destdir)
+def create_npmrc_file(registry, namespace=None, username=None, password=None):
+ """Creates a npmrc file with authentication credentials populated based on provided username and password"""
+
+ # Create a temporary file we can store the npm authentication within
+ npmrc_file = tempfile.NamedTemporaryFile(mode="w", buffering=1).name
+
+ # Convert "username:password" string into base64 auth string
+ base64_auth_string = base64.b64encode(f"{username}:{password}".encode('utf-8')).decode('utf-8')
+
+ # Remove protocol from registry URL
+ registry = registry.replace('https://', '').replace('http://', '')
+
+ # Create the npmrc file with the authentication parameters
+ npm_auth_string = f"//{registry}/:_auth=\"{base64_auth_string}\""
+
+ with open(npmrc_file, 'w') as file:
+ file.write(npm_auth_string)
+ file.write("\n")
+
+ # Add namespace registry string if namespace is provided
+ if namespace:
+ npm_registry_string = f"@{namespace}:registry=https://{registry}"
+ file.write(npm_registry_string)
+ file.write("\n")
+
+ return npmrc_file
+
class NpmEnvironment(object):
"""
Using a npm config file seems more reliable than using cli arguments.
@@ -142,6 +178,9 @@ class Npm(FetchMethod):
ud.package = None
ud.version = None
ud.registry = None
+ ud.username = None
+ ud.password = None
+ ud.namespace = None
# Get the 'package' parameter
if "package" in ud.parm:
@@ -154,6 +193,16 @@ class Npm(FetchMethod):
if "version" in ud.parm:
ud.version = ud.parm.get("version")
+ if "username" in ud.parm:
+ ud.username = ud.parm.get("username")
+
+ if "password" in ud.parm:
+ ud.password = ud.parm.get("password")
+
+ if "namespace" in ud.parm:
+ ud.namespace = ud.parm.get("namespace")
+ ud.package = f"@{ud.namespace}/{ud.package}"
+
if not ud.version:
raise MissingParameterError("Parameter 'version' required", ud.url)
@@ -189,7 +238,16 @@ class Npm(FetchMethod):
args.append(("registry", ud.registry))
pkgver = shlex.quote(ud.package + "@" + ud.version)
cmd = ud.basecmd + " view %s" % pkgver
- env = NpmEnvironment(d)
+
+ # Create an npmrc file if a username and password was supplied to the npm SRC_URI
+ npmrc_file = None
+ if (ud.username is not None and ud.password is not None):
+ try:
+ npmrc_file = create_npmrc_file(ud.registry, ud.namespace, ud.username, ud.password)
+ except Exception as e:
+ bb.warn(f"Error creating npmrc file: {e}")
+
+ env = NpmEnvironment(d, [], npmrc=npmrc_file)
check_network_access(d, cmd, ud.registry)
view_string = env.run(cmd, args=args)
@@ -224,6 +282,10 @@ class Npm(FetchMethod):
uri = URI(tarball_url)
uri.params["downloadfilename"] = ud.localfile
+ if (ud.username is not None and ud.password is not None):
+ uri.params["user"] = ud.username
+ uri.params["pswd"] = ud.password
+
integrity = view.get("dist", {}).get("integrity")
shasum = view.get("dist", {}).get("shasum")