github.com/loafoe/cli@v7.1.0+incompatible/command/v7/auth_command_test.go (about)

     1  package v7_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	"code.cloudfoundry.org/cli/api/uaa"
     7  	"code.cloudfoundry.org/cli/api/uaa/constant"
     8  	"code.cloudfoundry.org/cli/api/uaa/uaaversion"
     9  	"code.cloudfoundry.org/cli/command/commandfakes"
    10  	"code.cloudfoundry.org/cli/command/translatableerror"
    11  	. "code.cloudfoundry.org/cli/command/v7"
    12  	"code.cloudfoundry.org/cli/command/v7/v7fakes"
    13  	"code.cloudfoundry.org/cli/util/ui"
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  	. "github.com/onsi/gomega/gbytes"
    17  )
    18  
    19  var _ = Describe("auth Command", func() {
    20  	var (
    21  		cmd        AuthCommand
    22  		testUI     *ui.UI
    23  		fakeActor  *v7fakes.FakeActor
    24  		fakeConfig *commandfakes.FakeConfig
    25  		binaryName string
    26  		err        error
    27  	)
    28  
    29  	BeforeEach(func() {
    30  		testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer())
    31  		fakeActor = new(v7fakes.FakeActor)
    32  		fakeConfig = new(commandfakes.FakeConfig)
    33  
    34  		cmd = AuthCommand{
    35  			BaseCommand: BaseCommand{
    36  				UI:     testUI,
    37  				Config: fakeConfig,
    38  				Actor:  fakeActor,
    39  			},
    40  		}
    41  
    42  		binaryName = "faceman"
    43  		fakeConfig.BinaryNameReturns(binaryName)
    44  		fakeConfig.UAAOAuthClientReturns("cf")
    45  		fakeConfig.APIVersionReturns("3.85.0")
    46  	})
    47  
    48  	JustBeforeEach(func() {
    49  		err = cmd.Execute(nil)
    50  	})
    51  
    52  	When("--origin are set", func() {
    53  		BeforeEach(func() {
    54  			cmd.Origin = "some-origin"
    55  		})
    56  
    57  		When("the UAA is below the minimum API version", func() {
    58  			BeforeEach(func() {
    59  				fakeActor.UAAAPIVersionReturns(uaaversion.InvalidUAAClientVersion)
    60  			})
    61  
    62  			It("returns an API version error", func() {
    63  				Expect(err).To(MatchError(translatableerror.MinimumUAAAPIVersionNotMetError{
    64  					Command:        "Option '--origin'",
    65  					MinimumVersion: uaaversion.MinUAAClientVersion,
    66  				}))
    67  			})
    68  		})
    69  
    70  		When("--client-credentials set", func() {
    71  			BeforeEach(func() {
    72  				cmd.ClientCredentials = true
    73  				fakeActor.UAAAPIVersionReturns(uaaversion.MinUAAClientVersion)
    74  			})
    75  
    76  			It("returns an ArgumentCombinationError", func() {
    77  				Expect(err).To(MatchError(translatableerror.ArgumentCombinationError{
    78  					Args: []string{"--client-credentials", "--origin"},
    79  				}))
    80  			})
    81  		})
    82  	})
    83  
    84  	When("credentials are missing", func() {
    85  		When("username and password are both missing", func() {
    86  			It("raises an error", func() {
    87  				Expect(err).To(MatchError(translatableerror.MissingCredentialsError{
    88  					MissingUsername: true,
    89  					MissingPassword: true,
    90  				}))
    91  			})
    92  		})
    93  
    94  		When("username is missing", func() {
    95  			BeforeEach(func() {
    96  				cmd.RequiredArgs.Password = "mypassword"
    97  			})
    98  
    99  			It("raises an error", func() {
   100  				Expect(err).To(MatchError(translatableerror.MissingCredentialsError{
   101  					MissingUsername: true,
   102  				}))
   103  			})
   104  		})
   105  
   106  		When("password is missing", func() {
   107  			BeforeEach(func() {
   108  				cmd.RequiredArgs.Username = "myuser"
   109  			})
   110  
   111  			It("raises an error", func() {
   112  				Expect(err).To(MatchError(translatableerror.MissingCredentialsError{
   113  					MissingPassword: true,
   114  				}))
   115  			})
   116  		})
   117  	})
   118  
   119  	When("there is an auth error", func() {
   120  		BeforeEach(func() {
   121  			cmd.RequiredArgs.Username = "foo"
   122  			cmd.RequiredArgs.Password = "bar"
   123  
   124  			fakeConfig.TargetReturns("some-api-target")
   125  			fakeActor.AuthenticateReturns(uaa.UnauthorizedError{Message: "some message"})
   126  		})
   127  
   128  		It("returns a BadCredentialsError", func() {
   129  			Expect(err).To(MatchError(uaa.UnauthorizedError{Message: "some message"}))
   130  		})
   131  	})
   132  
   133  	When("there is an account locked error", func() {
   134  		BeforeEach(func() {
   135  			cmd.RequiredArgs.Username = "foo"
   136  			cmd.RequiredArgs.Password = "bar"
   137  
   138  			fakeConfig.TargetReturns("some-api-target")
   139  			fakeActor.AuthenticateReturns(uaa.AccountLockedError{Message: "some message"})
   140  		})
   141  
   142  		It("returns a BadCredentialsError", func() {
   143  			Expect(err).To(MatchError(uaa.AccountLockedError{Message: "some message"}))
   144  		})
   145  	})
   146  
   147  	When("there is a non-auth error", func() {
   148  		var expectedError error
   149  
   150  		BeforeEach(func() {
   151  			cmd.RequiredArgs.Username = "foo"
   152  			cmd.RequiredArgs.Password = "bar"
   153  
   154  			fakeConfig.TargetReturns("some-api-target")
   155  			expectedError = errors.New("my humps")
   156  
   157  			fakeActor.AuthenticateReturns(expectedError)
   158  		})
   159  
   160  		It("returns the error", func() {
   161  			Expect(err).To(MatchError(expectedError))
   162  		})
   163  	})
   164  
   165  	When("there are no input errors", func() {
   166  		var (
   167  			testID     string
   168  			testSecret string
   169  		)
   170  
   171  		BeforeEach(func() {
   172  			testID = "hello"
   173  			testSecret = "goodbye"
   174  
   175  			fakeConfig.TargetReturns("some-api-target")
   176  		})
   177  
   178  		When("--client-credentials is set", func() {
   179  			BeforeEach(func() {
   180  				cmd.ClientCredentials = true
   181  				cmd.RequiredArgs.Username = testID
   182  				cmd.RequiredArgs.Password = testSecret
   183  			})
   184  
   185  			It("outputs API target information and clears the targeted org and space", func() {
   186  				Expect(err).ToNot(HaveOccurred())
   187  
   188  				Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target()))
   189  				Expect(testUI.Out).To(Say(`Authenticating\.\.\.`))
   190  				Expect(testUI.Out).To(Say("OK"))
   191  				Expect(testUI.Out).To(Say("Use '%s target' to view or set your target org and space", binaryName))
   192  
   193  				Expect(fakeActor.AuthenticateCallCount()).To(Equal(1))
   194  				credentials, origin, grantType := fakeActor.AuthenticateArgsForCall(0)
   195  				ID := credentials["client_id"]
   196  				secret := credentials["client_secret"]
   197  				Expect(ID).To(Equal(testID))
   198  				Expect(secret).To(Equal(testSecret))
   199  				Expect(origin).To(BeEmpty())
   200  				Expect(grantType).To(Equal(constant.GrantTypeClientCredentials))
   201  			})
   202  		})
   203  
   204  		When("--client-credentials is not set", func() {
   205  			When("username and password are only provided as arguments", func() {
   206  				BeforeEach(func() {
   207  					cmd.RequiredArgs.Username = testID
   208  					cmd.RequiredArgs.Password = testSecret
   209  				})
   210  
   211  				When("the API version is older than the minimum supported API version for the v7 CLI", func() {
   212  					BeforeEach(func() {
   213  						fakeConfig.APIVersionReturns("3.83.0")
   214  					})
   215  					It("warns that the user is targeting an unsupported API version and that things may not work correctly", func() {
   216  						Expect(err).ToNot(HaveOccurred())
   217  						Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target()))
   218  						Expect(testUI.Err).To(Say("Warning: Your targeted API's version \\(3.83.0\\) is less than the minimum supported API version \\(3.85.0\\). Some commands may not function correctly."))
   219  					})
   220  				})
   221  
   222  				When("the API version is empty", func() {
   223  					BeforeEach(func() {
   224  						fakeConfig.APIVersionReturns("")
   225  					})
   226  					It("prints a warning message", func() {
   227  						Expect(err).ToNot(HaveOccurred())
   228  						Expect(testUI.Err).To(Say("Warning: unable to determine whether targeted API's version meets minimum supported."))
   229  					})
   230  				})
   231  
   232  				It("should NOT warn that the user is targeting an unsupported API version", func() {
   233  					Expect(testUI.Err).ToNot(Say("is less than the minimum supported API version"))
   234  				})
   235  
   236  				It("outputs API target information and clears the targeted org and space", func() {
   237  					Expect(err).ToNot(HaveOccurred())
   238  
   239  					Expect(testUI.Out).To(Say("API endpoint: %s", fakeConfig.Target()))
   240  					Expect(testUI.Out).To(Say(`Authenticating\.\.\.`))
   241  					Expect(testUI.Out).To(Say("OK"))
   242  					Expect(testUI.Out).To(Say("Use '%s target' to view or set your target org and space", binaryName))
   243  
   244  					Expect(fakeActor.AuthenticateCallCount()).To(Equal(1))
   245  					credentials, origin, grantType := fakeActor.AuthenticateArgsForCall(0)
   246  					username := credentials["username"]
   247  					password := credentials["password"]
   248  					Expect(username).To(Equal(testID))
   249  					Expect(password).To(Equal(testSecret))
   250  					Expect(origin).To(BeEmpty())
   251  					Expect(grantType).To(Equal(constant.GrantTypePassword))
   252  				})
   253  			})
   254  
   255  			When("the username and password are provided in env variables", func() {
   256  				var (
   257  					envUsername string
   258  					envPassword string
   259  				)
   260  
   261  				BeforeEach(func() {
   262  					envUsername = "banana"
   263  					envPassword = "potato"
   264  					fakeConfig.CFUsernameReturns(envUsername)
   265  					fakeConfig.CFPasswordReturns(envPassword)
   266  				})
   267  
   268  				When("username and password are not also provided as arguments", func() {
   269  					It("authenticates with the values in the env variables", func() {
   270  						Expect(err).ToNot(HaveOccurred())
   271  
   272  						Expect(fakeActor.AuthenticateCallCount()).To(Equal(1))
   273  						credentials, origin, _ := fakeActor.AuthenticateArgsForCall(0)
   274  						username := credentials["username"]
   275  						password := credentials["password"]
   276  						Expect(username).To(Equal(envUsername))
   277  						Expect(password).To(Equal(envPassword))
   278  						Expect(origin).To(BeEmpty())
   279  					})
   280  				})
   281  
   282  				When("username and password are also provided as arguments", func() {
   283  					BeforeEach(func() {
   284  						cmd.RequiredArgs.Username = testID
   285  						cmd.RequiredArgs.Password = testSecret
   286  					})
   287  
   288  					It("authenticates with the values from the command line args", func() {
   289  						Expect(err).ToNot(HaveOccurred())
   290  
   291  						Expect(fakeActor.AuthenticateCallCount()).To(Equal(1))
   292  						credentials, origin, _ := fakeActor.AuthenticateArgsForCall(0)
   293  						username := credentials["username"]
   294  						password := credentials["password"]
   295  						Expect(username).To(Equal(testID))
   296  						Expect(password).To(Equal(testSecret))
   297  						Expect(origin).To(BeEmpty())
   298  					})
   299  				})
   300  			})
   301  		})
   302  
   303  		When("a user has manually added their client credentials to the config file", func() {
   304  			BeforeEach(func() {
   305  				fakeConfig.UAAOAuthClientReturns("AClientsId")
   306  			})
   307  
   308  			When("the --client-credentials flag is not set", func() {
   309  				BeforeEach(func() {
   310  					cmd.ClientCredentials = false
   311  					cmd.RequiredArgs.Username = "some-username"
   312  					cmd.RequiredArgs.Password = "some-password"
   313  				})
   314  
   315  				It("fails with an error indicating manual client credentials are no longer supported in the config file", func() {
   316  					Expect(err).To(MatchError(translatableerror.ManualClientCredentialsError{}))
   317  				})
   318  			})
   319  		})
   320  	})
   321  
   322  	When("already logged in via client credentials", func() {
   323  		BeforeEach(func() {
   324  			fakeConfig.UAAGrantTypeReturns("client_credentials")
   325  		})
   326  
   327  		When("authenticating as a user", func() {
   328  			BeforeEach(func() {
   329  				cmd.ClientCredentials = false
   330  				cmd.RequiredArgs.Username = "some-username"
   331  				cmd.RequiredArgs.Password = "some-password"
   332  			})
   333  
   334  			It("returns an already logged in error", func() {
   335  				Expect(err).To(MatchError("Service account currently logged in. Use 'cf logout' to log out service account and try again."))
   336  				Expect(fakeConfig.UAAGrantTypeCallCount()).To(Equal(1))
   337  			})
   338  
   339  			It("the returned error is translatable", func() {
   340  				Expect(err).To(MatchError(translatableerror.PasswordGrantTypeLogoutRequiredError{}))
   341  			})
   342  		})
   343  
   344  		When("authenticating as a client", func() {
   345  			BeforeEach(func() {
   346  				cmd.ClientCredentials = true
   347  				cmd.RequiredArgs.Username = "some-client-id"
   348  				cmd.RequiredArgs.Password = "some-client-secret"
   349  			})
   350  			It("does not error", func() {
   351  				Expect(err).ToNot(HaveOccurred())
   352  				Expect(fakeConfig.UAAGrantTypeCallCount()).To(Equal(0))
   353  			})
   354  		})
   355  	})
   356  })