<commit_before>package cmd

import (
	"fmt"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"time"

	flags "github.com/jessevdk/go-flags"
	"github.com/mitchellh/cli"
	v1auth "github.com/nerdalize/nerd/nerd/client/auth/v1"
	v1authpayload "github.com/nerdalize/nerd/nerd/client/auth/v1/payload"
	"github.com/nerdalize/nerd/nerd/conf"
	"github.com/nerdalize/nerd/nerd/oauth"
	"github.com/nerdalize/nerd/pkg/kubeconfig"
	"github.com/nerdalize/nerd/pkg/populator"
	"github.com/pkg/errors"
	"github.com/skratchdot/open-golang/open"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

const (
	authorizeEndpoint = "o/authorize"
)

//Login command
type Login struct {
	Config string `long:"config-src" default:"oidc" default-mask:"" description:"type of configuration to use (from env, endpoint, or oidc)"`
	*command
}

//LoginFactory returns a factory method for the join command
func LoginFactory(ui cli.Ui) cli.CommandFactory {
	cmd := &Login{}
	cmd.command = createCommand(ui, cmd.Execute, cmd.Description, cmd.Usage, cmd, &ConfOpts{}, flags.PassAfterNonOption, "nerd login")

	t, ok := cmd.advancedOpts.(*ConfOpts)
	if !ok {
		return nil
	}
	t.ConfigFile = cmd.setConfig
	t.SessionFile = cmd.setSession
	return func() (cli.Command, error) {
		return cmd, nil
	}
}

//Execute runs the command
func (cmd *Login) Execute(args []string) (err error) {
	env := os.Getenv("NERD_ENV")
	if env == "staging" {
		cmd.config = conf.StagingDefaults()
	} else if env == "dev" {
		cmd.config = conf.DevDefaults(os.Getenv("NERD_API_ENDPOINT"))
	}
	authbase, err := url.Parse(cmd.config.Auth.APIEndpoint)
	if err != nil {
		return renderConfigError(err, "auth endpoint '%v' is not a valid URL", cmd.config.Auth.APIEndpoint)
	}
	authOpsClient := v1auth.NewOpsClient(v1auth.OpsClientConfig{
		Base:   authbase,
		Logger: cmd.Logger(),
	})
	randomState := randomString(32)
	doneCh := make(chan response)
	svr := &http.Server{
		Addr: cmd.config.Auth.OAuthLocalServer,
	}
	defer svr.Close()
	go spawnServer(svr, cmd.config.Auth, randomState, doneCh)

	err = open.Run(fmt.Sprintf("http://%s/oauth?state=%s", cmd.config.Auth.OAuthLocalServer, randomState))
	if err != nil {
		cmd.out.Info(fmt.Sprintf("Failed to open browser window, access the login at http://%s/oauth?state=%s", cmd.config.Auth.OAuthLocalServer, randomState))
	}

	oauthResponse := <-doneCh
	if oauthResponse.err != nil {
		return renderConfigError(oauthResponse.err, "failed to do oauth login")
	}

	out, err := authOpsClient.GetOAuthCredentials(oauthResponse.code, cmd.config.Auth.SecureClientID, cmd.config.Auth.SecureClientSecret, fmt.Sprintf("http://%s/oauth/callback", cmd.config.Auth.OAuthLocalServer))
	if err != nil {
		return renderConfigError(err, "failed to get oauth credentials")
	}

	expiration := time.Unix(time.Now().Unix()+int64(out.ExpiresIn), 0)
	err = cmd.session.WriteOAuth(out.AccessToken, out.RefreshToken, out.IDToken, expiration, out.Scope, out.TokenType)
	if err != nil {
		return renderConfigError(err, "failed to write oauth tokens to config")
	}<commit_msg>Change login command to always display login URL<commit_after>package cmd

import (
	"fmt"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"time"

	flags "github.com/jessevdk/go-flags"
	"github.com/mitchellh/cli"
	v1auth "github.com/nerdalize/nerd/nerd/client/auth/v1"
	v1authpayload "github.com/nerdalize/nerd/nerd/client/auth/v1/payload"
	"github.com/nerdalize/nerd/nerd/conf"
	"github.com/nerdalize/nerd/nerd/oauth"
	"github.com/nerdalize/nerd/pkg/kubeconfig"
	"github.com/nerdalize/nerd/pkg/populator"
	"github.com/pkg/errors"
	"github.com/skratchdot/open-golang/open"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

const (
	authorizeEndpoint = "o/authorize"
)

//Login command
type Login struct {
	Config string `long:"config-src" default:"oidc" default-mask:"" description:"type of configuration to use (from env, endpoint, or oidc)"`
	*command
}

//LoginFactory returns a factory method for the join command
func LoginFactory(ui cli.Ui) cli.CommandFactory {
	cmd := &Login{}
	cmd.command = createCommand(ui, cmd.Execute, cmd.Description, cmd.Usage, cmd, &ConfOpts{}, flags.PassAfterNonOption, "nerd login")

	t, ok := cmd.advancedOpts.(*ConfOpts)
	if !ok {
		return nil
	}
	t.ConfigFile = cmd.setConfig
	t.SessionFile = cmd.setSession
	return func() (cli.Command, error) {
		return cmd, nil
	}
}

//Execute runs the command
func (cmd *Login) Execute(args []string) (err error) {
	env := os.Getenv("NERD_ENV")
	if env == "staging" {
		cmd.config = conf.StagingDefaults()
	} else if env == "dev" {
		cmd.config = conf.DevDefaults(os.Getenv("NERD_API_ENDPOINT"))
	}
	authbase, err := url.Parse(cmd.config.Auth.APIEndpoint)
	if err != nil {
		return renderConfigError(err, "auth endpoint '%v' is not a valid URL", cmd.config.Auth.APIEndpoint)
	}
	authOpsClient := v1auth.NewOpsClient(v1auth.OpsClientConfig{
		Base:   authbase,
		Logger: cmd.Logger(),
	})
	randomState := randomString(32)
	doneCh := make(chan response)
	svr := &http.Server{
		Addr: cmd.config.Auth.OAuthLocalServer,
	}
	defer svr.Close()
	go spawnServer(svr, cmd.config.Auth, randomState, doneCh)

	cmd.out.Info(fmt.Sprintf("Access the login at http://%s/oauth?state=%s", cmd.config.Auth.OAuthLocalServer, randomState))

	// May fail, but we always display the login URL on stdout as well
	open.Run(fmt.Sprintf("http://%s/oauth?state=%s", cmd.config.Auth.OAuthLocalServer, randomState))

	oauthResponse := <-doneCh
	if oauthResponse.err != nil {
		return renderConfigError(oauthResponse.err, "failed to do oauth login")
	}

	out, err := authOpsClient.GetOAuthCredentials(oauthResponse.code, cmd.config.Auth.SecureClientID, cmd.config.Auth.SecureClientSecret, fmt.Sprintf("http://%s/oauth/callback", cmd.config.Auth.OAuthLocalServer))
	if err != nil {
		return renderConfigError(err, "failed to get oauth credentials")
	}

	expiration := time.Unix(time.Now().Unix()+int64(out.ExpiresIn), 0)
	err = cmd.session.WriteOAuth(out.AccessToken, out.RefreshToken, out.IDToken, expiration, out.Scope, out.TokenType)
	if err != nil {
		return renderConfigError(err, "failed to write oauth tokens to config")
	}
{'fraction_non_alphanumeric': 0.14733290488431877, 'fraction_numerical': 0.005141388174807198, 'mean_word_length': 4.742619926199262, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1941301', 'n_tokens_mistral': 2346, 'n_tokens_neox': 2294, 'n_words': 463}