github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/cf/commands/login_test.go (about) 1 package commands_test 2 3 import ( 4 "strconv" 5 6 "code.cloudfoundry.org/cli/cf/api/authentication/authenticationfakes" 7 "code.cloudfoundry.org/cli/cf/api/organizations/organizationsfakes" 8 "code.cloudfoundry.org/cli/cf/api/spaces/spacesfakes" 9 "code.cloudfoundry.org/cli/cf/commandregistry" 10 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 11 "code.cloudfoundry.org/cli/cf/configuration/coreconfig/coreconfigfakes" 12 "code.cloudfoundry.org/cli/cf/errors" 13 "code.cloudfoundry.org/cli/cf/models" 14 testcmd "code.cloudfoundry.org/cli/util/testhelpers/commands" 15 testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration" 16 testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 20 . "code.cloudfoundry.org/cli/util/testhelpers/matchers" 21 ) 22 23 var _ = Describe("Login Command", func() { 24 var ( 25 Flags []string 26 Config coreconfig.Repository 27 ui *testterm.FakeUI 28 authRepo *authenticationfakes.FakeRepository 29 endpointRepo *coreconfigfakes.FakeEndpointRepository 30 orgRepo *organizationsfakes.FakeOrganizationRepository 31 spaceRepo *spacesfakes.FakeSpaceRepository 32 33 org models.Organization 34 deps commandregistry.Dependency 35 36 minCLIVersion string 37 minRecommendedCLIVersion string 38 ) 39 40 updateCommandDependency := func(pluginCall bool) { 41 deps.UI = ui 42 deps.Config = Config 43 deps.RepoLocator = deps.RepoLocator.SetEndpointRepository(endpointRepo) 44 deps.RepoLocator = deps.RepoLocator.SetAuthenticationRepository(authRepo) 45 deps.RepoLocator = deps.RepoLocator.SetOrganizationRepository(orgRepo) 46 deps.RepoLocator = deps.RepoLocator.SetSpaceRepository(spaceRepo) 47 commandregistry.Commands.SetCommand(commandregistry.Commands.FindCommand("login").SetDependency(deps, pluginCall)) 48 } 49 50 listSpacesStub := func(spaces []models.Space) func(func(models.Space) bool) error { 51 return func(cb func(models.Space) bool) error { 52 var keepGoing bool 53 for _, s := range spaces { 54 keepGoing = cb(s) 55 if !keepGoing { 56 return nil 57 } 58 } 59 return nil 60 } 61 } 62 63 BeforeEach(func() { 64 Flags = []string{} 65 Config = testconfig.NewRepository() 66 ui = &testterm.FakeUI{} 67 authRepo = new(authenticationfakes.FakeRepository) 68 authRepo.AuthenticateStub = func(credentials map[string]string) error { 69 Config.SetAccessToken("my_access_token") 70 Config.SetRefreshToken("my_refresh_token") 71 return nil 72 } 73 endpointRepo = new(coreconfigfakes.FakeEndpointRepository) 74 minCLIVersion = "1.0.0" 75 minRecommendedCLIVersion = "1.0.0" 76 77 org = models.Organization{} 78 org.Name = "my-new-org" 79 org.GUID = "my-new-org-guid" 80 81 orgRepo = &organizationsfakes.FakeOrganizationRepository{} 82 orgRepo.ListOrgsReturns([]models.Organization{org}, nil) 83 84 space := models.Space{} 85 space.GUID = "my-space-guid" 86 space.Name = "my-space" 87 88 spaceRepo = new(spacesfakes.FakeSpaceRepository) 89 spaceRepo.ListSpacesStub = listSpacesStub([]models.Space{space}) 90 91 authRepo.GetLoginPromptsAndSaveUAAServerURLReturns(map[string]coreconfig.AuthPrompt{ 92 "username": { 93 DisplayName: "Username", 94 Type: coreconfig.AuthPromptTypeText, 95 }, 96 "password": { 97 DisplayName: "Password", 98 Type: coreconfig.AuthPromptTypePassword, 99 }, 100 }, nil) 101 }) 102 103 Context("interactive usage", func() { 104 JustBeforeEach(func() { 105 endpointRepo.GetCCInfoStub = func(endpoint string) (*coreconfig.CCInfo, string, error) { 106 return &coreconfig.CCInfo{ 107 APIVersion: "some-version", 108 AuthorizationEndpoint: "auth/endpoint", 109 DopplerEndpoint: "doppler/endpoint", 110 MinCLIVersion: minCLIVersion, 111 MinRecommendedCLIVersion: minRecommendedCLIVersion, 112 SSHOAuthClient: "some-client", 113 RoutingAPIEndpoint: "routing/endpoint", 114 }, endpoint, nil 115 } 116 }) 117 118 Describe("when there are a small number of organizations and spaces", func() { 119 var org2 models.Organization 120 var space2 models.Space 121 122 BeforeEach(func() { 123 org1 := models.Organization{} 124 org1.GUID = "some-org-guid" 125 org1.Name = "some-org" 126 127 org2 = models.Organization{} 128 org2.GUID = "my-new-org-guid" 129 org2.Name = "my-new-org" 130 131 space1 := models.Space{} 132 space1.GUID = "my-space-guid" 133 space1.Name = "my-space" 134 135 space2 = models.Space{} 136 space2.GUID = "some-space-guid" 137 space2.Name = "some-space" 138 139 orgRepo.ListOrgsReturns([]models.Organization{org1, org2}, nil) 140 spaceRepo.ListSpacesStub = listSpacesStub([]models.Space{space1, space2}) 141 spaceRepo.FindByNameStub = func(name string) (models.Space, error) { 142 m := map[string]models.Space{ 143 space1.Name: space1, 144 space2.Name: space2, 145 } 146 return m[name], nil 147 } 148 }) 149 150 It("lets the user select an org and space by number", func() { 151 orgRepo.FindByNameReturns(org2, nil) 152 OUT_OF_RANGE_CHOICE := "3" 153 ui.Inputs = []string{"api.example.com", "user@example.com", "password", OUT_OF_RANGE_CHOICE, "2", OUT_OF_RANGE_CHOICE, "1"} 154 155 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 156 157 Expect(ui.Outputs()).To(ContainSubstrings( 158 []string{"Select an org"}, 159 []string{"1. some-org"}, 160 []string{"2. my-new-org"}, 161 []string{"Select a space"}, 162 []string{"1. my-space"}, 163 []string{"2. some-space"}, 164 )) 165 166 Expect(Config.OrganizationFields().GUID).To(Equal("my-new-org-guid")) 167 Expect(Config.SpaceFields().GUID).To(Equal("my-space-guid")) 168 Expect(Config.AccessToken()).To(Equal("my_access_token")) 169 Expect(Config.RefreshToken()).To(Equal("my_refresh_token")) 170 171 Expect(Config.APIEndpoint()).To(Equal("api.example.com")) 172 Expect(Config.APIVersion()).To(Equal("some-version")) 173 Expect(Config.AuthenticationEndpoint()).To(Equal("auth/endpoint")) 174 Expect(Config.SSHOAuthClient()).To(Equal("some-client")) 175 Expect(Config.MinCLIVersion()).To(Equal("1.0.0")) 176 Expect(Config.MinRecommendedCLIVersion()).To(Equal("1.0.0")) 177 Expect(Config.DopplerEndpoint()).To(Equal("doppler/endpoint")) 178 Expect(Config.RoutingAPIEndpoint()).To(Equal("routing/endpoint")) 179 180 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 181 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("api.example.com")) 182 183 Expect(orgRepo.FindByNameArgsForCall(0)).To(Equal("my-new-org")) 184 Expect(spaceRepo.FindByNameArgsForCall(0)).To(Equal("my-space")) 185 186 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 187 }) 188 189 It("lets the user select an org and space by name", func() { 190 ui.Inputs = []string{"api.example.com", "user@example.com", "password", "my-new-org", "my-space"} 191 orgRepo.FindByNameReturns(org2, nil) 192 193 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 194 195 Expect(ui.Outputs()).To(ContainSubstrings( 196 []string{"Select an org"}, 197 []string{"1. some-org"}, 198 []string{"2. my-new-org"}, 199 []string{"Select a space"}, 200 []string{"1. my-space"}, 201 []string{"2. some-space"}, 202 )) 203 204 Expect(Config.OrganizationFields().GUID).To(Equal("my-new-org-guid")) 205 Expect(Config.SpaceFields().GUID).To(Equal("my-space-guid")) 206 Expect(Config.AccessToken()).To(Equal("my_access_token")) 207 Expect(Config.RefreshToken()).To(Equal("my_refresh_token")) 208 209 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 210 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("api.example.com")) 211 212 Expect(orgRepo.FindByNameArgsForCall(0)).To(Equal("my-new-org")) 213 Expect(spaceRepo.FindByNameArgsForCall(0)).To(Equal("my-space")) 214 215 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 216 }) 217 218 It("lets the user specify an org and space using flags", func() { 219 Flags = []string{"-a", "api.example.com", "-u", "user@example.com", "-p", "password", "-o", "my-new-org", "-s", "my-space"} 220 221 orgRepo.FindByNameReturns(org2, nil) 222 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 223 224 Expect(Config.OrganizationFields().GUID).To(Equal("my-new-org-guid")) 225 Expect(Config.SpaceFields().GUID).To(Equal("my-space-guid")) 226 Expect(Config.AccessToken()).To(Equal("my_access_token")) 227 Expect(Config.RefreshToken()).To(Equal("my_refresh_token")) 228 229 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 230 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("api.example.com")) 231 Expect(authRepo.AuthenticateCallCount()).To(Equal(1)) 232 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 233 "username": "user@example.com", 234 "password": "password", 235 })) 236 237 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 238 }) 239 240 It("doesn't ask the user for the API url if they have it in their config", func() { 241 orgRepo.FindByNameReturns(org, nil) 242 Config.SetAPIEndpoint("http://api.example.com") 243 244 Flags = []string{"-o", "my-new-org", "-s", "my-space"} 245 ui.Inputs = []string{"user@example.com", "password"} 246 247 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 248 249 Expect(Config.APIEndpoint()).To(Equal("http://api.example.com")) 250 Expect(Config.OrganizationFields().GUID).To(Equal("my-new-org-guid")) 251 Expect(Config.SpaceFields().GUID).To(Equal("my-space-guid")) 252 Expect(Config.AccessToken()).To(Equal("my_access_token")) 253 Expect(Config.RefreshToken()).To(Equal("my_refresh_token")) 254 255 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 256 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("http://api.example.com")) 257 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 258 }) 259 }) 260 261 It("displays an update notification", func() { 262 ui.Inputs = []string{"http://api.example.com", "user@example.com", "password"} 263 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 264 Expect(ui.NotifyUpdateIfNeededCallCount).To(Equal(1)) 265 }) 266 267 It("tries to get the organizations", func() { 268 Flags = []string{} 269 ui.Inputs = []string{"api.example.com", "user@example.com", "password", "my-org-1", "my-space"} 270 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 271 Expect(orgRepo.ListOrgsCallCount()).To(Equal(1)) 272 Expect(orgRepo.ListOrgsArgsForCall(0)).To(Equal(50)) 273 }) 274 275 Describe("when there are too many orgs to show", func() { 276 BeforeEach(func() { 277 organizations := []models.Organization{} 278 for i := 0; i < 60; i++ { 279 id := strconv.Itoa(i) 280 org := models.Organization{} 281 org.GUID = "my-org-guid-" + id 282 org.Name = "my-org-" + id 283 organizations = append(organizations, org) 284 } 285 orgRepo.ListOrgsReturns(organizations, nil) 286 orgRepo.FindByNameReturns(organizations[1], nil) 287 288 space1 := models.Space{} 289 space1.GUID = "my-space-guid" 290 space1.Name = "my-space" 291 292 space2 := models.Space{} 293 space2.GUID = "some-space-guid" 294 space2.Name = "some-space" 295 296 spaceRepo.ListSpacesStub = listSpacesStub([]models.Space{space1, space2}) 297 }) 298 299 It("doesn't display a list of orgs (the user must type the name)", func() { 300 ui.Inputs = []string{"api.example.com", "user@example.com", "password", "my-org-1", "my-space"} 301 302 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 303 304 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"my-org-2"})) 305 Expect(orgRepo.FindByNameArgsForCall(0)).To(Equal("my-org-1")) 306 Expect(Config.OrganizationFields().GUID).To(Equal("my-org-guid-1")) 307 }) 308 }) 309 310 Describe("when there is only a single org and space", func() { 311 It("does not ask the user to select an org/space", func() { 312 ui.Inputs = []string{"http://api.example.com", "user@example.com", "password"} 313 314 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 315 316 Expect(Config.OrganizationFields().GUID).To(Equal("my-new-org-guid")) 317 Expect(Config.SpaceFields().GUID).To(Equal("my-space-guid")) 318 Expect(Config.AccessToken()).To(Equal("my_access_token")) 319 Expect(Config.RefreshToken()).To(Equal("my_refresh_token")) 320 321 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 322 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("http://api.example.com")) 323 Expect(authRepo.AuthenticateCallCount()).To(Equal(1)) 324 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 325 "username": "user@example.com", 326 "password": "password", 327 })) 328 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 329 }) 330 }) 331 332 Describe("where there are no available orgs", func() { 333 BeforeEach(func() { 334 orgRepo.ListOrgsReturns([]models.Organization{}, nil) 335 spaceRepo.ListSpacesStub = listSpacesStub([]models.Space{}) 336 }) 337 338 It("does not as the user to select an org", func() { 339 ui.Inputs = []string{"http://api.example.com", "user@example.com", "password"} 340 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 341 342 Expect(Config.OrganizationFields().GUID).To(Equal("")) 343 Expect(Config.SpaceFields().GUID).To(Equal("")) 344 Expect(Config.AccessToken()).To(Equal("my_access_token")) 345 Expect(Config.RefreshToken()).To(Equal("my_refresh_token")) 346 347 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 348 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("http://api.example.com")) 349 Expect(authRepo.AuthenticateCallCount()).To(Equal(1)) 350 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 351 "username": "user@example.com", 352 "password": "password", 353 })) 354 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 355 }) 356 }) 357 358 Describe("when there is only a single org and no spaces", func() { 359 BeforeEach(func() { 360 orgRepo.ListOrgsReturns([]models.Organization{org}, nil) 361 spaceRepo.ListSpacesStub = listSpacesStub([]models.Space{}) 362 }) 363 364 It("does not ask the user to select a space", func() { 365 ui.Inputs = []string{"http://api.example.com", "user@example.com", "password"} 366 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 367 368 Expect(Config.OrganizationFields().GUID).To(Equal("my-new-org-guid")) 369 Expect(Config.SpaceFields().GUID).To(Equal("")) 370 Expect(Config.AccessToken()).To(Equal("my_access_token")) 371 Expect(Config.RefreshToken()).To(Equal("my_refresh_token")) 372 373 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 374 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("http://api.example.com")) 375 Expect(authRepo.AuthenticateCallCount()).To(Equal(1)) 376 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 377 "username": "user@example.com", 378 "password": "password", 379 })) 380 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 381 }) 382 }) 383 384 Describe("login prompts", func() { 385 BeforeEach(func() { 386 authRepo.GetLoginPromptsAndSaveUAAServerURLReturns(map[string]coreconfig.AuthPrompt{ 387 "account_number": { 388 DisplayName: "Account Number", 389 Type: coreconfig.AuthPromptTypeText, 390 }, 391 "username": { 392 DisplayName: "Username", 393 Type: coreconfig.AuthPromptTypeText, 394 }, 395 "passcode": { 396 DisplayName: "It's a passcode, what you want it to be???", 397 Type: coreconfig.AuthPromptTypePassword, 398 }, 399 "password": { 400 DisplayName: "Your Password", 401 Type: coreconfig.AuthPromptTypePassword, 402 }, 403 }, nil) 404 }) 405 406 Context("when the user does not provide the --sso flag", func() { 407 It("prompts the user for 'password' prompt and any text type prompt", func() { 408 ui.Inputs = []string{"api.example.com", "the-username", "the-account-number", "the-password"} 409 410 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 411 412 Expect(ui.Prompts).To(ContainSubstrings( 413 []string{"API endpoint"}, 414 []string{"Account Number"}, 415 []string{"Username"}, 416 )) 417 Expect(ui.PasswordPrompts).To(ContainSubstrings([]string{"Your Password"})) 418 Expect(ui.PasswordPrompts).ToNot(ContainSubstrings( 419 []string{"passcode"}, 420 )) 421 422 Expect(authRepo.AuthenticateCallCount()).To(Equal(1)) 423 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 424 "account_number": "the-account-number", 425 "username": "the-username", 426 "password": "the-password", 427 })) 428 }) 429 }) 430 431 Context("when the user does provide the --sso flag", func() { 432 It("only prompts the user for the passcode type prompts", func() { 433 Flags = []string{"--sso", "-a", "api.example.com"} 434 ui.Inputs = []string{"the-one-time-code"} 435 436 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 437 438 Expect(ui.Prompts).To(BeEmpty()) 439 Expect(ui.PasswordPrompts).To(ContainSubstrings([]string{"passcode"})) 440 Expect(authRepo.AuthenticateCallCount()).To(Equal(1)) 441 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 442 "passcode": "the-one-time-code", 443 })) 444 }) 445 }) 446 447 It("takes the password from the -p flag", func() { 448 Flags = []string{"-p", "the-password"} 449 ui.Inputs = []string{"api.example.com", "the-username", "the-account-number", "the-pin"} 450 451 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 452 453 Expect(ui.PasswordPrompts).ToNot(ContainSubstrings([]string{"Your Password"})) 454 Expect(authRepo.AuthenticateCallCount()).To(Equal(1)) 455 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 456 "account_number": "the-account-number", 457 "username": "the-username", 458 "password": "the-password", 459 })) 460 }) 461 462 It("tries 3 times for the password-type prompts", func() { 463 authRepo.AuthenticateReturns(errors.New("Error authenticating.")) 464 ui.Inputs = []string{"api.example.com", "the-username", "the-account-number", 465 "the-password-1", "the-password-2", "the-password-3"} 466 467 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 468 469 Expect(authRepo.AuthenticateCallCount()).To(Equal(3)) 470 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 471 "username": "the-username", 472 "account_number": "the-account-number", 473 "password": "the-password-1", 474 })) 475 Expect(authRepo.AuthenticateArgsForCall(1)).To(Equal(map[string]string{ 476 "username": "the-username", 477 "account_number": "the-account-number", 478 "password": "the-password-2", 479 })) 480 Expect(authRepo.AuthenticateArgsForCall(2)).To(Equal(map[string]string{ 481 "username": "the-username", 482 "account_number": "the-account-number", 483 "password": "the-password-3", 484 })) 485 486 Expect(ui.Outputs()).To(ContainSubstrings([]string{"FAILED"})) 487 }) 488 489 It("prompts user for password again if password given on the cmd line fails", func() { 490 authRepo.AuthenticateReturns(errors.New("Error authenticating.")) 491 492 Flags = []string{"-p", "the-password-1"} 493 494 ui.Inputs = []string{"api.example.com", "the-username", "the-account-number", 495 "the-password-2", "the-password-3"} 496 497 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 498 499 Expect(authRepo.AuthenticateCallCount()).To(Equal(3)) 500 Expect(authRepo.AuthenticateArgsForCall(0)).To(Equal(map[string]string{ 501 "username": "the-username", 502 "account_number": "the-account-number", 503 "password": "the-password-1", 504 })) 505 Expect(authRepo.AuthenticateArgsForCall(1)).To(Equal(map[string]string{ 506 "username": "the-username", 507 "account_number": "the-account-number", 508 "password": "the-password-2", 509 })) 510 Expect(authRepo.AuthenticateArgsForCall(2)).To(Equal(map[string]string{ 511 "username": "the-username", 512 "account_number": "the-account-number", 513 "password": "the-password-3", 514 })) 515 516 Expect(ui.Outputs()).To(ContainSubstrings([]string{"FAILED"})) 517 }) 518 }) 519 }) 520 521 Describe("updates to the config", func() { 522 BeforeEach(func() { 523 Config.SetAPIEndpoint("api.the-old-endpoint.com") 524 Config.SetAccessToken("the-old-access-token") 525 Config.SetRefreshToken("the-old-refresh-token") 526 endpointRepo.GetCCInfoStub = func(endpoint string) (*coreconfig.CCInfo, string, error) { 527 return &coreconfig.CCInfo{ 528 APIVersion: "some-version", 529 AuthorizationEndpoint: "auth/endpoint", 530 DopplerEndpoint: "doppler/endpoint", 531 MinCLIVersion: minCLIVersion, 532 MinRecommendedCLIVersion: minRecommendedCLIVersion, 533 SSHOAuthClient: "some-client", 534 RoutingAPIEndpoint: "routing/endpoint", 535 }, endpoint, nil 536 } 537 538 }) 539 540 JustBeforeEach(func() { 541 testcmd.RunCLICommand("login", Flags, nil, updateCommandDependency, false, ui) 542 }) 543 544 var ItShowsTheTarget = func() { 545 It("shows the target", func() { 546 Expect(ui.ShowConfigurationCalled).To(BeTrue()) 547 }) 548 } 549 550 var ItDoesntShowTheTarget = func() { 551 It("does not show the target info", func() { 552 Expect(ui.ShowConfigurationCalled).To(BeFalse()) 553 }) 554 } 555 556 var ItFails = func() { 557 It("fails", func() { 558 Expect(ui.Outputs()).To(ContainSubstrings([]string{"FAILED"})) 559 }) 560 } 561 562 var ItSucceeds = func() { 563 It("runs successfully", func() { 564 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"FAILED"})) 565 Expect(ui.Outputs()).To(ContainSubstrings([]string{"OK"})) 566 }) 567 } 568 569 Describe("when the user is setting an API", func() { 570 BeforeEach(func() { 571 Flags = []string{"-a", "https://api.the-server.com", "-u", "the-user-name", "-p", "the-password"} 572 }) 573 574 Describe("when the --skip-ssl-validation flag is provided", func() { 575 BeforeEach(func() { 576 Flags = append(Flags, "--skip-ssl-validation") 577 }) 578 579 Describe("setting api endpoint is successful", func() { 580 BeforeEach(func() { 581 Config.SetSSLDisabled(false) 582 }) 583 584 ItSucceeds() 585 ItShowsTheTarget() 586 587 It("stores the API endpoint and the skip-ssl flag", func() { 588 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 589 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("https://api.the-server.com")) 590 Expect(Config.IsSSLDisabled()).To(BeTrue()) 591 }) 592 }) 593 594 Describe("setting api endpoint failed", func() { 595 BeforeEach(func() { 596 Config.SetSSLDisabled(true) 597 endpointRepo.GetCCInfoReturns(nil, "", errors.New("API endpoint not found")) 598 }) 599 600 ItFails() 601 ItDoesntShowTheTarget() 602 603 It("clears the entire config", func() { 604 Expect(Config.APIEndpoint()).To(BeEmpty()) 605 Expect(Config.IsSSLDisabled()).To(BeFalse()) 606 Expect(Config.AccessToken()).To(BeEmpty()) 607 Expect(Config.RefreshToken()).To(BeEmpty()) 608 Expect(Config.OrganizationFields().GUID).To(BeEmpty()) 609 Expect(Config.SpaceFields().GUID).To(BeEmpty()) 610 }) 611 }) 612 }) 613 614 Describe("when the --skip-ssl-validation flag is not provided", func() { 615 Describe("setting api endpoint is successful", func() { 616 BeforeEach(func() { 617 Config.SetSSLDisabled(true) 618 }) 619 620 ItSucceeds() 621 ItShowsTheTarget() 622 623 It("updates the API endpoint and enables SSL validation", func() { 624 Expect(endpointRepo.GetCCInfoCallCount()).To(Equal(1)) 625 Expect(endpointRepo.GetCCInfoArgsForCall(0)).To(Equal("https://api.the-server.com")) 626 Expect(Config.IsSSLDisabled()).To(BeFalse()) 627 }) 628 }) 629 630 Describe("setting api endpoint failed", func() { 631 BeforeEach(func() { 632 Config.SetSSLDisabled(true) 633 endpointRepo.GetCCInfoReturns(nil, "", errors.New("API endpoint not found")) 634 }) 635 636 ItFails() 637 ItDoesntShowTheTarget() 638 639 It("clears the entire config", func() { 640 Expect(Config.APIEndpoint()).To(BeEmpty()) 641 Expect(Config.IsSSLDisabled()).To(BeFalse()) 642 Expect(Config.AccessToken()).To(BeEmpty()) 643 Expect(Config.RefreshToken()).To(BeEmpty()) 644 Expect(Config.OrganizationFields().GUID).To(BeEmpty()) 645 Expect(Config.SpaceFields().GUID).To(BeEmpty()) 646 }) 647 }) 648 }) 649 650 Describe("when there is an invalid SSL cert", func() { 651 BeforeEach(func() { 652 endpointRepo.GetCCInfoReturns(nil, "", errors.NewInvalidSSLCert("https://bobs-burgers.com", "SELF SIGNED SADNESS")) 653 ui.Inputs = []string{"bobs-burgers.com"} 654 }) 655 656 It("fails and suggests the user skip SSL validation", func() { 657 Expect(ui.Outputs()).To(ContainSubstrings( 658 []string{"FAILED"}, 659 []string{"SSL Cert", "https://bobs-burgers.com"}, 660 []string{"TIP", "login", "--skip-ssl-validation"}, 661 )) 662 }) 663 664 ItDoesntShowTheTarget() 665 }) 666 }) 667 668 Describe("when user is logging in and not setting the api endpoint", func() { 669 BeforeEach(func() { 670 Flags = []string{"-u", "the-user-name", "-p", "the-password"} 671 }) 672 673 Describe("when the --skip-ssl-validation flag is provided", func() { 674 BeforeEach(func() { 675 Flags = append(Flags, "--skip-ssl-validation") 676 Config.SetSSLDisabled(false) 677 }) 678 679 It("disables SSL validation", func() { 680 Expect(Config.IsSSLDisabled()).To(BeTrue()) 681 }) 682 }) 683 684 Describe("when the --skip-ssl-validation flag is not provided", func() { 685 BeforeEach(func() { 686 Config.SetSSLDisabled(true) 687 }) 688 689 It("should not change config's SSLDisabled flag", func() { 690 Expect(Config.IsSSLDisabled()).To(BeTrue()) 691 }) 692 }) 693 694 Describe("and the login fails authenticaton", func() { 695 BeforeEach(func() { 696 authRepo.AuthenticateReturns(errors.New("Error authenticating.")) 697 698 Config.SetSSLDisabled(true) 699 700 Flags = []string{"-u", "user@example.com"} 701 ui.Inputs = []string{"password", "password2", "password3", "password4"} 702 }) 703 704 ItFails() 705 ItShowsTheTarget() 706 707 It("does not change the api endpoint or SSL setting in the config", func() { 708 Expect(Config.APIEndpoint()).To(Equal("api.the-old-endpoint.com")) 709 Expect(Config.IsSSLDisabled()).To(BeTrue()) 710 }) 711 712 It("clears Access Token, Refresh Token, Org, and Space in the config", func() { 713 Expect(Config.AccessToken()).To(BeEmpty()) 714 Expect(Config.RefreshToken()).To(BeEmpty()) 715 Expect(Config.OrganizationFields().GUID).To(BeEmpty()) 716 Expect(Config.SpaceFields().GUID).To(BeEmpty()) 717 }) 718 }) 719 }) 720 721 Describe("and the login fails to target an org", func() { 722 BeforeEach(func() { 723 Flags = []string{"-u", "user@example.com", "-p", "password", "-o", "nonexistentorg", "-s", "my-space"} 724 orgRepo.FindByNameReturns(models.Organization{}, errors.New("No org")) 725 Config.SetSSLDisabled(true) 726 }) 727 728 ItFails() 729 ItShowsTheTarget() 730 731 It("does not update the api endpoint or ssl setting in the config", func() { 732 Expect(Config.APIEndpoint()).To(Equal("api.the-old-endpoint.com")) 733 Expect(Config.IsSSLDisabled()).To(BeTrue()) 734 }) 735 736 It("clears Org, and Space in the config", func() { 737 Expect(Config.OrganizationFields().GUID).To(BeEmpty()) 738 Expect(Config.SpaceFields().GUID).To(BeEmpty()) 739 }) 740 }) 741 742 Describe("and the login fails to target a space", func() { 743 BeforeEach(func() { 744 Flags = []string{"-u", "user@example.com", "-p", "password", "-o", "my-new-org", "-s", "nonexistent"} 745 orgRepo.FindByNameReturns(org, nil) 746 spaceRepo.FindByNameReturns(models.Space{}, errors.New("find-by-name-err")) 747 748 Config.SetSSLDisabled(true) 749 }) 750 751 ItFails() 752 ItShowsTheTarget() 753 754 It("does not update the api endpoint or ssl setting in the config", func() { 755 Expect(Config.APIEndpoint()).To(Equal("api.the-old-endpoint.com")) 756 Expect(Config.IsSSLDisabled()).To(BeTrue()) 757 }) 758 759 It("updates the org in the config", func() { 760 Expect(Config.OrganizationFields().GUID).To(Equal("my-new-org-guid")) 761 }) 762 763 It("clears the space in the config", func() { 764 Expect(Config.SpaceFields().GUID).To(BeEmpty()) 765 }) 766 }) 767 768 Describe("and the login succeeds", func() { 769 BeforeEach(func() { 770 orgRepo.FindByNameReturns(models.Organization{ 771 OrganizationFields: models.OrganizationFields{ 772 Name: "new-org", 773 GUID: "new-org-guid", 774 }, 775 }, nil) 776 777 space1 := models.Space{} 778 space1.GUID = "new-space-guid" 779 space1.Name = "new-space-name" 780 spaceRepo.ListSpacesStub = listSpacesStub([]models.Space{space1}) 781 spaceRepo.FindByNameReturns(space1, nil) 782 783 authRepo.AuthenticateStub = func(credentials map[string]string) error { 784 Config.SetAccessToken("new_access_token") 785 Config.SetRefreshToken("new_refresh_token") 786 return nil 787 } 788 789 Flags = []string{"-u", "user@example.com", "-p", "password", "-o", "new-org", "-s", "new-space"} 790 791 Config.SetAPIEndpoint("api.the-old-endpoint.com") 792 Config.SetSSLDisabled(true) 793 }) 794 795 ItSucceeds() 796 ItShowsTheTarget() 797 798 It("does not update the api endpoint or SSL setting", func() { 799 Expect(Config.APIEndpoint()).To(Equal("api.the-old-endpoint.com")) 800 Expect(Config.IsSSLDisabled()).To(BeTrue()) 801 }) 802 803 It("updates the config", func() { 804 Expect(Config.AccessToken()).To(Equal("new_access_token")) 805 Expect(Config.RefreshToken()).To(Equal("new_refresh_token")) 806 Expect(Config.OrganizationFields().GUID).To(Equal("new-org-guid")) 807 Expect(Config.SpaceFields().GUID).To(Equal("new-space-guid")) 808 809 Expect(Config.APIVersion()).To(Equal("some-version")) 810 Expect(Config.AuthenticationEndpoint()).To(Equal("auth/endpoint")) 811 Expect(Config.SSHOAuthClient()).To(Equal("some-client")) 812 Expect(Config.MinCLIVersion()).To(Equal("1.0.0")) 813 Expect(Config.MinRecommendedCLIVersion()).To(Equal("1.0.0")) 814 Expect(Config.DopplerEndpoint()).To(Equal("doppler/endpoint")) 815 Expect(Config.RoutingAPIEndpoint()).To(Equal("routing/endpoint")) 816 817 }) 818 }) 819 }) 820 })