11package utils
22
33import (
4+ "encoding/base64"
45 "fmt"
5- outFormat "github.com/jfrog/jfrog-cli-core/v2/common/format"
6- "net/http"
7- "strings"
8-
96 "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
7+ "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/npm"
8+ "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/yarn"
109 "github.com/jfrog/jfrog-cli-core/v2/common/build"
10+ outFormat "github.com/jfrog/jfrog-cli-core/v2/common/format"
11+ "github.com/jfrog/jfrog-cli-core/v2/common/project"
12+ "github.com/jfrog/jfrog-cli-core/v2/utils/config"
1113 "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
1214 "github.com/jfrog/jfrog-client-go/auth"
1315 "github.com/jfrog/jfrog-client-go/http/httpclient"
1416 clientutils "github.com/jfrog/jfrog-client-go/utils"
1517 "github.com/jfrog/jfrog-client-go/utils/errorutils"
1618 "github.com/jfrog/jfrog-client-go/utils/log"
19+ "net/http"
20+ "strings"
1721)
1822
1923const (
2024 minSupportedArtifactoryVersionForNpmCmds = "5.5.2"
21- NpmConfigAuthKey = "_auth"
22- NpmConfigAuthTokenKey = "_authToken"
23- npmAuthRestApi = "api/npm/auth"
25+
26+ NpmConfigAuthKey = "_auth"
27+ // Supported only in npm version 9 and above.
28+ NpmConfigAuthTokenKey = "_authToken"
29+ NpmConfigRegistryKey = "registry"
30+ npmAuthRestApi = "api/npm/auth"
2431)
2532
2633// Constructs npm auth config and registry, manually or by requesting the Artifactory /npm/auth endpoint.
@@ -37,7 +44,7 @@ func GetArtifactoryNpmRepoDetails(repo string, authArtDetails auth.ServiceDetail
3744 return "" , "" , err
3845 }
3946
40- registry = getNpmRepositoryUrl (repo , authArtDetails .GetUrl ())
47+ registry = GetNpmRepositoryUrl (repo , authArtDetails .GetUrl ())
4148 return
4249}
4350
@@ -59,7 +66,7 @@ func getNpmAuth(authArtDetails auth.ServiceDetails, isNpmAuthLegacyVersion bool)
5966
6067// Manually constructs the npm authToken config data.
6168func constructNpmAuthToken (token string ) string {
62- return fmt .Sprintf ("%s = %s\n always-auth = true " , NpmConfigAuthTokenKey , token )
69+ return fmt .Sprintf ("%s = %s" , NpmConfigAuthTokenKey , token )
6370}
6471
6572func validateArtifactoryVersionForNpmCmds (artDetails auth.ServiceDetails ) error {
@@ -93,12 +100,8 @@ func getNpmAuthFromArtifactory(artDetails auth.ServiceDetails) (npmAuth string,
93100 return string (body ), nil
94101}
95102
96- func getNpmRepositoryUrl (repo , url string ) string {
97- if ! strings .HasSuffix (url , "/" ) {
98- url += "/"
99- }
100- url += "api/npm/" + repo
101- return url
103+ func GetNpmRepositoryUrl (repositoryName , artifactoryUrl string ) string {
104+ return strings .TrimSuffix (artifactoryUrl , "/" ) + "/api/npm/" + repositoryName
102105}
103106
104107// Remove all the none npm CLI flags from args.
@@ -125,3 +128,120 @@ func ExtractNpmOptionsFromArgs(args []string) (detailedSummary, xrayScan bool, s
125128 cleanArgs , buildConfig , err = build .ExtractBuildDetailsFromArgs (cleanArgs )
126129 return
127130}
131+
132+ // NpmrcYarnrcManager is responsible for configuring npm and Yarn registries
133+ // and authentication settings based on the specified project type.
134+ type NpmrcYarnrcManager struct {
135+ // buildTool represents the project type, either NPM or Yarn.
136+ buildTool project.ProjectType
137+ // repoUrl holds the URL to the npm or Yarn repository.
138+ repoUrl string
139+ // serverDetails contains configuration details for the Artifactory server.
140+ serverDetails * config.ServerDetails
141+ }
142+
143+ // NewNpmrcYarnrcManager initializes a new NpmrcYarnrcManager with the given project type,
144+ // repository name, and Artifactory server details.
145+ func NewNpmrcYarnrcManager (buildTool project.ProjectType , repoName string , serverDetails * config.ServerDetails ) * NpmrcYarnrcManager {
146+ repoUrl := GetNpmRepositoryUrl (repoName , serverDetails .ArtifactoryUrl )
147+ return & NpmrcYarnrcManager {
148+ buildTool : buildTool ,
149+ repoUrl : repoUrl ,
150+ serverDetails : serverDetails ,
151+ }
152+ }
153+
154+ // ConfigureRegistry sets the registry URL in the npmrc or yarnrc file.
155+ func (nm * NpmrcYarnrcManager ) ConfigureRegistry () error {
156+ return nm .configSet (NpmConfigRegistryKey , nm .repoUrl )
157+ }
158+
159+ // ConfigureAuth configures authentication in npmrc or yarnrc using token or basic auth,
160+ // or clears authentication for anonymous access.
161+ func (nm * NpmrcYarnrcManager ) ConfigureAuth () error {
162+ authArtDetails , err := nm .serverDetails .CreateArtAuthConfig ()
163+ if err != nil {
164+ return err
165+ }
166+
167+ // Configure authentication based on available credentials.
168+ switch {
169+ case authArtDetails .GetAccessToken () != "" :
170+ return nm .handleNpmrcTokenAuth (authArtDetails .GetAccessToken ())
171+ case authArtDetails .GetUser () != "" && authArtDetails .GetPassword () != "" :
172+ return nm .handleNpmrcBasicAuth (authArtDetails .GetUser (), authArtDetails .GetPassword ())
173+ default :
174+ return nm .handleNpmAnonymousAccess ()
175+ }
176+ }
177+
178+ // handleNpmrcTokenAuth sets the token in the npmrc or yarnrc file and clears basic auth if it exists.
179+ func (nm * NpmrcYarnrcManager ) handleNpmrcTokenAuth (token string ) error {
180+ authKey := nm .createAuthKey (NpmConfigAuthTokenKey )
181+ if err := nm .configSet (authKey , token ); err != nil {
182+ return err
183+ }
184+ return nm .removeNpmrcBasicAuthIfExists ()
185+ }
186+
187+ // handleNpmrcBasicAuth sets basic auth credentials and clears any token-based auth.
188+ func (nm * NpmrcYarnrcManager ) handleNpmrcBasicAuth (user , password string ) error {
189+ authKey := nm .createAuthKey (NpmConfigAuthKey )
190+ authValue := basicAuthBase64Encode (user , password )
191+ if err := nm .configSet (authKey , authValue ); err != nil {
192+ return err
193+ }
194+ return nm .removeNpmrcTokenAuthIfExists ()
195+ }
196+
197+ // handleNpmAnonymousAccess removes any existing authentication settings for anonymous access.
198+ func (nm * NpmrcYarnrcManager ) handleNpmAnonymousAccess () error {
199+ if err := nm .removeNpmrcBasicAuthIfExists (); err != nil {
200+ return err
201+ }
202+ return nm .removeNpmrcTokenAuthIfExists ()
203+ }
204+
205+ // removeNpmrcBasicAuthIfExists deletes basic auth credentials if present.
206+ func (nm * NpmrcYarnrcManager ) removeNpmrcBasicAuthIfExists () error {
207+ return nm .configDelete (nm .createAuthKey (NpmConfigAuthKey ))
208+ }
209+
210+ // removeNpmrcTokenAuthIfExists deletes token auth credentials if present.
211+ func (nm * NpmrcYarnrcManager ) removeNpmrcTokenAuthIfExists () error {
212+ return nm .configDelete (nm .createAuthKey (NpmConfigAuthTokenKey ))
213+ }
214+
215+ // configSet applies a configuration setting in npmrc or yarnrc, based on the build tool type.
216+ func (nm * NpmrcYarnrcManager ) configSet (key , value string ) error {
217+ switch nm .buildTool {
218+ case project .Npm :
219+ return npm .ConfigSet (key , value , nm .buildTool .String ())
220+ case project .Yarn :
221+ return yarn .ConfigSet (key , value , nm .buildTool .String (), false )
222+ default :
223+ return errorutils .CheckError (fmt .Errorf ("unsupported build tool: %s" , nm .buildTool ))
224+ }
225+ }
226+
227+ // configDelete removes a configuration setting from npmrc or yarnrc, based on the build tool type.
228+ func (nm * NpmrcYarnrcManager ) configDelete (key string ) error {
229+ switch nm .buildTool {
230+ case project .Npm :
231+ return npm .ConfigDelete (key , nm .buildTool .String ())
232+ case project .Yarn :
233+ return yarn .ConfigDelete (key , nm .buildTool .String ())
234+ default :
235+ return errorutils .CheckError (fmt .Errorf ("unsupported build tool: %s" , nm .buildTool ))
236+ }
237+ }
238+
239+ // createAuthKey generates the correct authentication key for npm or Yarn, based on the repo URL.
240+ func (nm * NpmrcYarnrcManager ) createAuthKey (keySuffix string ) string {
241+ return fmt .Sprintf ("//%s:%s" , strings .TrimPrefix (nm .repoUrl , "https://" ), keySuffix )
242+ }
243+
244+ // basicAuthBase64Encode encodes user credentials in Base64 for basic authentication.
245+ func basicAuthBase64Encode (user , password string ) string {
246+ return base64 .StdEncoding .EncodeToString ([]byte (fmt .Sprintf ("%s:%s" , user , password )))
247+ }
0 commit comments