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