From 9d506745cc3d045bfa0025d55b369f814fec2a4e Mon Sep 17 00:00:00 2001 From: Matheus Sampaio Queiroga Date: Sat, 9 Dec 2023 18:44:26 +0000 Subject: [PATCH] Add git helper Add support to tea login with helper same another tools and `gh` Co-authored-by: Matheus Sampaio Queiroga Co-committed-by: Matheus Sampaio Queiroga --- cmd/login.go | 1 + cmd/login/add.go | 9 ++- cmd/login/helper.go | 110 +++++++++++++++++++++++++++++++++++ docs/CLI.md | 2 + modules/interact/login.go | 17 ++++-- modules/interact/prompts.go | 18 ++++++ modules/task/login_create.go | 28 ++++++++- 7 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 cmd/login/helper.go diff --git a/cmd/login.go b/cmd/login.go index c090fca..c487b15 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -28,6 +28,7 @@ var CmdLogin = cli.Command{ &login.CmdLoginEdit, &login.CmdLoginDelete, &login.CmdLoginSetDefault, + &login.CmdLoginHelper, }, } diff --git a/cmd/login/add.go b/cmd/login/add.go index 3f91ed7..7b6d44b 100644 --- a/cmd/login/add.go +++ b/cmd/login/add.go @@ -74,6 +74,11 @@ var CmdLoginAdd = cli.Command{ Aliases: []string{"a"}, Usage: "Use SSH public key or SSH fingerprint to login (needs a running ssh-agent with ssh key loaded)", }, + &cli.BoolFlag{ + Name: "helper", + Aliases: []string{"j"}, + Usage: "Add helper", + }, }, Action: runLoginAdd, } @@ -101,5 +106,7 @@ func runLoginAdd(ctx *cli.Context) error { ctx.String("ssh-agent-key"), ctx.Bool("insecure"), sshAgent, - !ctx.Bool("no-version-check")) + !ctx.Bool("no-version-check"), + ctx.Bool("helper"), + ) } diff --git a/cmd/login/helper.go b/cmd/login/helper.go new file mode 100644 index 0000000..38a2740 --- /dev/null +++ b/cmd/login/helper.go @@ -0,0 +1,110 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package login + +import ( + "bufio" + "fmt" + "log" + "net/url" + "os" + "strings" + + "code.gitea.io/tea/modules/config" + "code.gitea.io/tea/modules/task" + "github.com/urfave/cli/v2" +) + +// CmdLoginHelper represents to login a gitea helper. +var CmdLoginHelper = cli.Command{ + Name: "helper", + Aliases: []string{"git-credential"}, + Usage: "Git helper", + Description: `Git helper`, + Hidden: true, + Subcommands: []*cli.Command{ + { + Name: "store", + Description: "Command drops", + Aliases: []string{"erase"}, + Action: func(ctx *cli.Context) error { + return nil + }, + }, + { + Name: "setup", + Description: "Setup helper to tea authenticate", + Action: func(ctx *cli.Context) error { + logins, err := config.GetLogins() + if err != nil { + return err + } + for loginIndex := range logins { + login := logins[loginIndex] + err = task.SetupHelper(login) + if err != nil { + return err + } + fmt.Printf("Added %s\n", login.Name) + } + return nil + }, + }, + { + Name: "get", + Description: "Get token to auth", + Action: func(cmd *cli.Context) error { + wants := map[string]string{} + s := bufio.NewScanner(os.Stdin) + for s.Scan() { + line := s.Text() + if line == "" { + break + } + parts := strings.SplitN(line, "=", 2) + if len(parts) < 2 { + continue + } + key, value := parts[0], parts[1] + if key == "url" { + u, err := url.Parse(value) + if err != nil { + return err + } + wants["protocol"] = u.Scheme + wants["host"] = u.Host + wants["path"] = u.Path + wants["username"] = u.User.Username() + wants["password"], _ = u.User.Password() + } else { + wants[key] = value + } + } + + if len(wants["host"]) == 0 { + log.Fatal("Require hostname") + } else if len(wants["protocol"]) == 0 { + wants["protocol"] = "http" + } + + userConfig := config.GetLoginByHost(wants["host"]) + if len(userConfig.Token) == 0 { + log.Fatal("User no set") + } + + host, err := url.Parse(userConfig.URL) + if err != nil { + return err + } + + _, err = fmt.Fprintf(os.Stdout, "protocol=%s\nhost=%s\nusername=%s\npassword=%s\n", host.Scheme, host.Host, userConfig.User, userConfig.Token) + if err != nil { + return err + } + + return nil + }, + }, + }, +} diff --git a/docs/CLI.md b/docs/CLI.md index 6224a92..d6bfd7e 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -51,6 +51,8 @@ List Gitea logins Add a Gitea login +**--helper, -j**: Add helper + **--insecure, -i**: Disable TLS verification **--name, -n**="": Login name diff --git a/modules/interact/login.go b/modules/interact/login.go index a1e54fc..adf5c25 100644 --- a/modules/interact/login.go +++ b/modules/interact/login.go @@ -17,10 +17,11 @@ import ( func CreateLogin() error { var ( name, token, user, passwd, sshKey, giteaURL, sshCertPrincipal, sshKeyFingerprint string - insecure, sshAgent, versionCheck bool + insecure, sshAgent, versionCheck, helper bool ) versionCheck = true + helper = false promptI := &survey.Input{Message: "URL of Gitea instance: "} if err := survey.AskOne(promptI, &giteaURL, survey.WithValidator(survey.Required)); err != nil { @@ -37,12 +38,12 @@ func CreateLogin() error { return err } - promptI = &survey.Input{Message: "Name of new Login [" + name + "]: "} + promptI = &survey.Input{Message: "Name of new Login: ", Default: name} if err := survey.AskOne(promptI, &name); err != nil { return err } - loginMethod, err := promptSelect("Login with: ", []string{"token", "ssh-key/certificate"}, "", "") + loginMethod, err := promptSelectV2("Login with: ", []string{"token", "ssh-key/certificate"}) if err != nil { return err } @@ -131,6 +132,14 @@ func CreateLogin() error { return err } + promptYN = &survey.Confirm{ + Message: "Add git helper: ", + Default: false, + } + if err = survey.AskOne(promptYN, &helper); err != nil { + return err + } + promptYN = &survey.Confirm{ Message: "Check version of Gitea instance: ", Default: true, @@ -141,5 +150,5 @@ func CreateLogin() error { } - return task.CreateLogin(name, token, user, passwd, sshKey, giteaURL, sshCertPrincipal, sshKeyFingerprint, insecure, sshAgent, versionCheck) + return task.CreateLogin(name, token, user, passwd, sshKey, giteaURL, sshCertPrincipal, sshKeyFingerprint, insecure, sshAgent, versionCheck, helper) } diff --git a/modules/interact/prompts.go b/modules/interact/prompts.go index ef03568..cb5c375 100644 --- a/modules/interact/prompts.go +++ b/modules/interact/prompts.go @@ -127,6 +127,24 @@ func promptMultiSelect(prompt string, options []string, customVal string) ([]str return promptCustomVal(prompt, customVal, selection) } +// promptSelectV2 creates a generic select prompt +func promptSelectV2(prompt string, options []string) (string, error) { + if len(options) == 0 { + return "", nil + } + var selection string + promptA := &survey.Select{ + Message: prompt, + Options: options, + VimMode: true, + Default: options[0], + } + if err := survey.AskOne(promptA, &selection); err != nil { + return "", err + } + return selection, nil +} + // promptSelect creates a generic select prompt, with processing of custom values or none-option. func promptSelect(prompt string, options []string, customVal, noneVal string) (string, error) { var selection string diff --git a/modules/task/login_create.go b/modules/task/login_create.go index 5e63329..3a548e5 100644 --- a/modules/task/login_create.go +++ b/modules/task/login_create.go @@ -6,6 +6,7 @@ package task import ( "fmt" "os" + "os/exec" "time" "code.gitea.io/tea/modules/config" @@ -14,8 +15,28 @@ import ( "code.gitea.io/sdk/gitea" ) +// SetupHelper add tea helper to config global +func SetupHelper(login config.Login) error { + // Remove all helpers + exec.Command("git", "config", "--global", "--unset-all", fmt.Sprintf("credential.%s.helper", login.URL)).Run() + + // + _, err := exec.Command("git", "config", "--global", fmt.Sprintf("credential.%s.helper", login.URL), "").Output() + if err != nil { + return err + } + + // Add tea helper + _, err = exec.Command("git", "config", "--global", "--add", fmt.Sprintf("credential.%s.helper", login.URL), "!tea login helper").Output() + if err != nil { + return err + } + + return nil +} + // CreateLogin create a login to be stored in config -func CreateLogin(name, token, user, passwd, sshKey, giteaURL, sshCertPrincipal, sshKeyFingerprint string, insecure, sshAgent, versionCheck bool) error { +func CreateLogin(name, token, user, passwd, sshKey, giteaURL, sshCertPrincipal, sshKeyFingerprint string, insecure, sshAgent, versionCheck, addHelper bool) error { // checks ... // ... if we have a url if len(giteaURL) == 0 { @@ -104,6 +125,11 @@ func CreateLogin(name, token, user, passwd, sshKey, giteaURL, sshCertPrincipal, } fmt.Printf("Login as %s on %s successful. Added this login as %s\n", login.User, login.URL, login.Name) + if addHelper { + if err = SetupHelper(login); err != nil { + return err + } + } return nil }