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:
6543 2020-10-02 15:57:48 +00:00
parent 3ee5501257
commit e23f56e81c
8 changed files with 119 additions and 72 deletions

View File

@ -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
}

View File

@ -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()
}

View File

@ -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)

View File

@ -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"

View File

@ -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

41
modules/print/login.go Normal file
View File

@ -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)
}

View File

@ -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
)

View File

@ -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