Add Detail View for Login (#212)
Impruve & Refactor AddLogin Impruve login comands Remove unused Package + Vars Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/212 Reviewed-by: Norwin <noerw@noreply.gitea.io> Reviewed-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
parent
3ee5501257
commit
e23f56e81c
29
cmd/login.go
29
cmd/login.go
|
@ -5,7 +5,11 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/tea/cmd/login"
|
"code.gitea.io/tea/cmd/login"
|
||||||
|
"code.gitea.io/tea/modules/config"
|
||||||
|
"code.gitea.io/tea/modules/print"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +20,8 @@ var CmdLogin = cli.Command{
|
||||||
Aliases: []string{"login"},
|
Aliases: []string{"login"},
|
||||||
Usage: "Log in to a Gitea server",
|
Usage: "Log in to a Gitea server",
|
||||||
Description: `Log in to a Gitea server`,
|
Description: `Log in to a Gitea server`,
|
||||||
Action: login.RunLoginAddInteractive, // TODO show list if no arg & detail if login as arg
|
ArgsUsage: "[<login name>]",
|
||||||
|
Action: runLogins,
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
&login.CmdLoginList,
|
&login.CmdLoginList,
|
||||||
&login.CmdLoginAdd,
|
&login.CmdLoginAdd,
|
||||||
|
@ -24,3 +29,25 @@ var CmdLogin = cli.Command{
|
||||||
&login.CmdLoginSetDefault,
|
&login.CmdLoginSetDefault,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runLogins(ctx *cli.Context) error {
|
||||||
|
if ctx.Args().Len() == 1 {
|
||||||
|
return runLoginDetail(ctx.Args().First())
|
||||||
|
}
|
||||||
|
return login.RunLoginList(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runLoginDetail(name string) error {
|
||||||
|
if err := config.LoadConfig(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
l := config.GetLoginByName(name)
|
||||||
|
if l == nil {
|
||||||
|
fmt.Printf("Login '%s' do not exist\n\n", name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
print.LoginDetails(l)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
var CmdLoginAdd = cli.Command{
|
var CmdLoginAdd = cli.Command{
|
||||||
Name: "add",
|
Name: "add",
|
||||||
Usage: "Add a Gitea login",
|
Usage: "Add a Gitea login",
|
||||||
Description: `Add a Gitea login`,
|
Description: `Add a Gitea login, without args it will create one interactively`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
|
@ -25,10 +25,9 @@ var CmdLoginAdd = cli.Command{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "url",
|
Name: "url",
|
||||||
Aliases: []string{"u"},
|
Aliases: []string{"u"},
|
||||||
Value: "https://try.gitea.io",
|
Value: "https://gitea.com",
|
||||||
EnvVars: []string{"GITEA_SERVER_URL"},
|
EnvVars: []string{"GITEA_SERVER_URL"},
|
||||||
Usage: "Server URL",
|
Usage: "Server URL",
|
||||||
Required: true,
|
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "token",
|
Name: "token",
|
||||||
|
@ -65,7 +64,12 @@ var CmdLoginAdd = cli.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func runLoginAdd(ctx *cli.Context) error {
|
func runLoginAdd(ctx *cli.Context) error {
|
||||||
// TODO: if no args -> interactive
|
// if no args create login interactive
|
||||||
|
if ctx.Args().Len() == 0 {
|
||||||
|
return interact.CreateLogin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// else use args to add login
|
||||||
return config.AddLogin(
|
return config.AddLogin(
|
||||||
ctx.String("name"),
|
ctx.String("name"),
|
||||||
ctx.String("token"),
|
ctx.String("token"),
|
||||||
|
@ -75,9 +79,3 @@ func runLoginAdd(ctx *cli.Context) error {
|
||||||
ctx.String("url"),
|
ctx.String("url"),
|
||||||
ctx.Bool("insecure"))
|
ctx.Bool("insecure"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunLoginAddInteractive create login interactive
|
|
||||||
// TODO: should be unexported
|
|
||||||
func RunLoginAddInteractive(_ *cli.Context) error {
|
|
||||||
return interact.CreateLogin()
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,11 +21,12 @@ var CmdLoginList = cli.Command{
|
||||||
Aliases: []string{"list"},
|
Aliases: []string{"list"},
|
||||||
Usage: "List Gitea logins",
|
Usage: "List Gitea logins",
|
||||||
Description: `List Gitea logins`,
|
Description: `List Gitea logins`,
|
||||||
Action: runLoginList,
|
Action: RunLoginList,
|
||||||
Flags: []cli.Flag{&flags.OutputFlag},
|
Flags: []cli.Flag{&flags.OutputFlag},
|
||||||
}
|
}
|
||||||
|
|
||||||
func runLoginList(ctx *cli.Context) error {
|
// RunLoginList list all logins
|
||||||
|
func RunLoginList(ctx *cli.Context) error {
|
||||||
err := config.LoadConfig()
|
err := config.LoadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
6
main.go
6
main.go
|
@ -11,7 +11,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/tea/cmd"
|
"code.gitea.io/tea/cmd"
|
||||||
"code.gitea.io/tea/modules/setting"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
@ -22,11 +21,6 @@ var Version = "development"
|
||||||
// Tags holds the build tags used
|
// Tags holds the build tags used
|
||||||
var Tags = ""
|
var Tags = ""
|
||||||
|
|
||||||
func init() {
|
|
||||||
setting.AppVer = Version
|
|
||||||
setting.AppBuiltWith = formatBuiltWith(Tags)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "tea"
|
app.Name = "tea"
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/tea/modules/utils"
|
"code.gitea.io/tea/modules/utils"
|
||||||
|
@ -30,8 +31,10 @@ type Login struct {
|
||||||
// optional path to the private key
|
// optional path to the private key
|
||||||
SSHKey string `yaml:"ssh_key"`
|
SSHKey string `yaml:"ssh_key"`
|
||||||
Insecure bool `yaml:"insecure"`
|
Insecure bool `yaml:"insecure"`
|
||||||
// optional gitea username
|
// User is username from gitea
|
||||||
User string `yaml:"user"`
|
User string `yaml:"user"`
|
||||||
|
// Created is auto created unix timestamp
|
||||||
|
Created int64 `yaml:"created"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client returns a client to operate Gitea API
|
// Client returns a client to operate Gitea API
|
||||||
|
@ -120,9 +123,29 @@ func GetLoginByName(name string) *Login {
|
||||||
|
|
||||||
// AddLogin add login to config ( global var & file)
|
// AddLogin add login to config ( global var & file)
|
||||||
func AddLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bool) error {
|
func AddLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bool) error {
|
||||||
|
// checks ...
|
||||||
|
// ... if we have a url
|
||||||
if len(giteaURL) == 0 {
|
if len(giteaURL) == 0 {
|
||||||
log.Fatal("You have to input Gitea server URL")
|
log.Fatal("You have to input Gitea server URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := LoadConfig()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Unable to load config file " + yamlConfigPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, l := range Config.Logins {
|
||||||
|
// ... if there already exist a login with same name
|
||||||
|
if strings.ToLower(l.Name) == strings.ToLower(name) {
|
||||||
|
return fmt.Errorf("login name '%s' has already been used", l.Name)
|
||||||
|
}
|
||||||
|
// ... if we already use this token
|
||||||
|
if l.Token == token {
|
||||||
|
return fmt.Errorf("token already been used, delete login '%s' first", l.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// .. if we have enough information to authenticate
|
||||||
if len(token) == 0 && (len(user)+len(passwd)) == 0 {
|
if len(token) == 0 && (len(user)+len(passwd)) == 0 {
|
||||||
log.Fatal("No token set")
|
log.Fatal("No token set")
|
||||||
} else if len(user) != 0 && len(passwd) == 0 {
|
} else if len(user) != 0 && len(passwd) == 0 {
|
||||||
|
@ -131,22 +154,19 @@ func AddLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bool)
|
||||||
log.Fatal("No user set")
|
log.Fatal("No user set")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize URL
|
||||||
serverURL, err := utils.NormalizeURL(giteaURL)
|
serverURL, err := utils.NormalizeURL(giteaURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Unable to parse URL", err)
|
log.Fatal("Unable to parse URL", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = LoadConfig()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("Unable to load config file " + yamlConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
login := Login{
|
login := Login{
|
||||||
Name: name,
|
Name: name,
|
||||||
URL: serverURL.String(),
|
URL: serverURL.String(),
|
||||||
Token: token,
|
Token: token,
|
||||||
Insecure: insecure,
|
Insecure: insecure,
|
||||||
SSHKey: sshKey,
|
SSHKey: sshKey,
|
||||||
|
Created: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(token) == 0 {
|
if len(token) == 0 {
|
||||||
|
@ -156,6 +176,7 @@ func AddLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify if authentication works and get user info
|
||||||
u, _, err := login.Client().GetMyUserInfo()
|
u, _, err := login.Client().GetMyUserInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -169,11 +190,14 @@ func AddLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = addLoginToConfig(login)
|
// we do not have a method to get SSH config from api,
|
||||||
if err != nil {
|
// so we just use the hostname
|
||||||
log.Fatal(err)
|
login.SSHHost = serverURL.Hostname()
|
||||||
}
|
|
||||||
|
|
||||||
|
// save login to global var
|
||||||
|
Config.Logins = append(Config.Logins, login)
|
||||||
|
|
||||||
|
// save login to config file
|
||||||
err = SaveConfig()
|
err = SaveConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -223,33 +247,6 @@ func GenerateLoginName(url, user string) (string, error) {
|
||||||
return name, nil
|
return name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addLoginToConfig add a login to global Config var
|
|
||||||
func addLoginToConfig(login Login) error {
|
|
||||||
for _, l := range Config.Logins {
|
|
||||||
if l.Name == login.Name {
|
|
||||||
if l.URL == login.URL && l.Token == login.Token {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errors.New("Login name has already been used")
|
|
||||||
}
|
|
||||||
if l.URL == login.URL && l.Token == login.Token {
|
|
||||||
return errors.New("Login for this URL and token already exists")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(login.SSHHost) == 0 {
|
|
||||||
u, err := url.Parse(login.URL)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
login.SSHHost = u.Hostname()
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Logins = append(Config.Logins, login)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitCommand returns repository and *Login based on flags
|
// InitCommand returns repository and *Login based on flags
|
||||||
func InitCommand(repoValue, loginValue, remoteValue string) (*Login, string, string) {
|
func InitCommand(repoValue, loginValue, remoteValue string) (*Login, string, string) {
|
||||||
var login *Login
|
var login *Login
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package print
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/tea/modules/config"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/glamour"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LoginDetails print login entry to stdout
|
||||||
|
func LoginDetails(login *config.Login) {
|
||||||
|
|
||||||
|
in := fmt.Sprintf("# %s\n\n[@%s](%s/%s)\n",
|
||||||
|
login.Name,
|
||||||
|
login.User,
|
||||||
|
strings.TrimSuffix(login.URL, "/"),
|
||||||
|
login.User,
|
||||||
|
)
|
||||||
|
if len(login.SSHKey) != 0 {
|
||||||
|
in += fmt.Sprintf("\nSSH Key: '%s' via %s\n",
|
||||||
|
login.SSHKey,
|
||||||
|
login.SSHHost,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
in += fmt.Sprintf("\nCreated: %s", time.Unix(login.Created, 0).Format(time.RFC822))
|
||||||
|
|
||||||
|
out, err := glamour.Render(in, getGlamourTheme())
|
||||||
|
if err != nil {
|
||||||
|
// TODO: better Error handling
|
||||||
|
fmt.Printf("Error:\n%v\n\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Print(out)
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package setting
|
|
||||||
|
|
||||||
// App related variables
|
|
||||||
var (
|
|
||||||
AppVer string
|
|
||||||
AppBuiltWith string
|
|
||||||
)
|
|
|
@ -24,7 +24,7 @@ func NormalizeURL(raw string) (*url.URL, error) {
|
||||||
if !strings.HasPrefix(raw, "http") {
|
if !strings.HasPrefix(raw, "http") {
|
||||||
prefix = "https://"
|
prefix = "https://"
|
||||||
}
|
}
|
||||||
return url.Parse(prefix + raw)
|
return url.Parse(strings.TrimSuffix(prefix+raw, "/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOwnerAndRepo return repoOwner and repoName
|
// GetOwnerAndRepo return repoOwner and repoName
|
||||||
|
|
Loading…
Reference in New Issue