<commit_before>package commands

import (
	"cf/api"
	"cf/configuration"
	term "cf/terminal"
	"encoding/base64"
	"fmt"
	"github.com/codegangsta/cli"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

type AuthenticationResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
}

const maxLoginTries = 3

type Login struct {
	ui        term.UI
	orgRepo   api.OrganizationRepository
	spaceRepo api.SpaceRepository
}

func NewLogin(ui term.UI, orgRepo api.OrganizationRepository, spaceRepo api.SpaceRepository) (l Login) {
	l.ui = ui
	l.orgRepo = orgRepo
	l.spaceRepo = spaceRepo
	return
}

func (l Login) Run(c *cli.Context) {
	config, err := configuration.Load()
	if err != nil {
		l.ui.Failed("Error loading configuration", err)
		return
	}

	l.ui.Say("target: %s", term.Cyan(config.Target))
	email := l.ui.Ask("Email%s", term.Cyan(">"))

	for i := 0; i < maxLoginTries; i++ {
		password := l.ui.Ask("Password%s", term.Cyan(">"))
		l.ui.Say("Authenticating...")

		response, err := l.authenticate(config.AuthorizationEndpoint, email, password)

		if err != nil {
			l.ui.Failed("Error Authenticating", err)
			continue
		}

		config.AccessToken = fmt.Sprintf("%s %s", response.TokenType, response.AccessToken)
		err = config.Save()

		if err != nil {
			l.ui.Failed("Error Persisting Session", err)
			return
		}
		l.ui.Ok()

		l.targetOrganization(config)
		l.targetSpace(config)

		return
	}
}

func (l Login) authenticate(endpoint string, email string, password string) (response AuthenticationResponse, err error) {
	data := url.Values{
		"username":   {email},
		"password":   {password},
		"grant_type": {"password"},
		"scope":      {""},
	}

	request, err := http.NewRequest("POST", endpoint+"/oauth/token", strings.NewReader(data.Encode()))
	if err != nil {
		return
	}
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte("cf:")))

	err = api.PerformRequest(request, &response)

	return
}

func (l Login) targetOrganization(config *configuration.Configuration) {
	organizations, err := l.orgRepo.FindOrganizations(config)

	if err != nil {
		l.ui.Failed("Error fetching organizations.", err)
		return
	}

	if len(organizations) < 2 {
		return
	}

	for i, org := range organizations {
		l.ui.Say("%s: %s", term.Green(strconv.Itoa(i+1)), org.Name)
	}

	index, err := strconv.Atoi(l.ui.Ask("Organization%s", term.Cyan(">")))

	if err != nil || index > len(organizations) {
		l.ui.Failed("Invalid number", err)
		l.targetOrganization(config)
		return
	}

	selectedOrg := organizations[index-1]
	config.Organization = selectedOrg
	err = config.Save()

	if err != nil {
		l.ui.Failed("Error saving organization: %s", err)
		return
	}

	l.ui.Say("Targeting org %s...", term.Cyan(selectedOrg.Name))
	l.ui.Ok()
}

func (l Login) targetSpace(config *configuration.Configuration) {
	spaces, err := l.spaceRepo.FindSpaces(config)

	if err != nil {
		l.ui.Failed("Error fetching spaces.", err)
		return
	}

	if len(spaces) < 2 {
		return
	}

	for i, space := range spaces {
		l.ui.Say("%s: %s", term.Green(strconv.Itoa(i+1)), space.Name)
	}

	index, err := strconv.Atoi(l.ui.Ask("Space%s", term.Cyan(">")))
<commit_msg>Check number of spaces before trying to target<commit_after>package commands

import (
	"cf/api"
	"cf/configuration"
	term "cf/terminal"
	"encoding/base64"
	"fmt"
	"github.com/codegangsta/cli"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

type AuthenticationResponse struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
}

const maxLoginTries = 3

type Login struct {
	ui        term.UI
	orgRepo   api.OrganizationRepository
	spaceRepo api.SpaceRepository
}

func NewLogin(ui term.UI, orgRepo api.OrganizationRepository, spaceRepo api.SpaceRepository) (l Login) {
	l.ui = ui
	l.orgRepo = orgRepo
	l.spaceRepo = spaceRepo
	return
}

func (l Login) Run(c *cli.Context) {
	config, err := configuration.Load()
	if err != nil {
		l.ui.Failed("Error loading configuration", err)
		return
	}

	l.ui.Say("target: %s", term.Cyan(config.Target))
	email := l.ui.Ask("Email%s", term.Cyan(">"))

	for i := 0; i < maxLoginTries; i++ {
		password := l.ui.Ask("Password%s", term.Cyan(">"))
		l.ui.Say("Authenticating...")

		response, err := l.authenticate(config.AuthorizationEndpoint, email, password)

		if err != nil {
			l.ui.Failed("Error Authenticating", err)
			continue
		}

		config.AccessToken = fmt.Sprintf("%s %s", response.TokenType, response.AccessToken)
		err = config.Save()

		if err != nil {
			l.ui.Failed("Error Persisting Session", err)
			return
		}
		l.ui.Ok()

		l.targetOrganization(config)
		l.targetSpace(config)

		return
	}
}

func (l Login) authenticate(endpoint string, email string, password string) (response AuthenticationResponse, err error) {
	data := url.Values{
		"username":   {email},
		"password":   {password},
		"grant_type": {"password"},
		"scope":      {""},
	}

	request, err := http.NewRequest("POST", endpoint+"/oauth/token", strings.NewReader(data.Encode()))
	if err != nil {
		return
	}
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	request.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte("cf:")))

	err = api.PerformRequest(request, &response)

	return
}

func (l Login) targetOrganization(config *configuration.Configuration) {
	organizations, err := l.orgRepo.FindOrganizations(config)

	if err != nil {
		l.ui.Failed("Error fetching organizations.", err)
		return
	}

	if len(organizations) < 2 {
		return
	}

	for i, org := range organizations {
		l.ui.Say("%s: %s", term.Green(strconv.Itoa(i+1)), org.Name)
	}

	index, err := strconv.Atoi(l.ui.Ask("Organization%s", term.Cyan(">")))

	if err != nil || index > len(organizations) {
		l.ui.Failed("Invalid number", err)
		l.targetOrganization(config)
		return
	}

	selectedOrg := organizations[index-1]
	config.Organization = selectedOrg
	err = config.Save()

	if err != nil {
		l.ui.Failed("Error saving organization: %s", err)
		return
	}

	l.ui.Say("Targeting org %s...", term.Cyan(selectedOrg.Name))
	l.ui.Ok()
}

func (l Login) targetSpace(config *configuration.Configuration) {
	spaces, err := l.spaceRepo.FindSpaces(config)

	if len(spaces) < 2 {
		return
	}

	if err != nil {
		l.ui.Failed("Error fetching spaces.", err)
		return
	}

	for i, space := range spaces {
		l.ui.Say("%s: %s", term.Green(strconv.Itoa(i+1)), space.Name)
	}

	index, err := strconv.Atoi(l.ui.Ask("Space%s", term.Cyan(">")))

{'fraction_non_alphanumeric': 0.16409943571755375, 'fraction_numerical': 0.0033551929235931064, 'mean_word_length': 4.1234375, 'pattern_counts': {'":': 8, '<': 9, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2453863', 'n_tokens_mistral': 2502, 'n_tokens_neox': 2343, 'n_words': 507}