1
0
mirror of https://gitea.com/jolheiser/sip synced 2024-11-26 07:33:48 +01:00

Move log in/out commands to tokens command

Signed-off-by: jolheiser <john.olheiser@gmail.com>
This commit is contained in:
jolheiser 2020-02-17 20:57:51 -06:00
parent b0816086dd
commit 039c227402
No known key found for this signature in database
GPG Key ID: B853ADA5DA7BBF7A
8 changed files with 166 additions and 196 deletions

@ -10,13 +10,12 @@ If no `upstream` repository is found, `upstream` becomes synonymous with `origin
* Configuration `sip config` * Configuration `sip config`
* Change the default `origin` remote name `sip config origin` * Change the default `origin` remote name `sip config origin`
* Change the default `upstream` remote name `sip config upstrea` * Change the default `upstream` remote name `sip config upstrea`
* Login `sip login` * Tokens `sip tokens`
* Add a user token for API usage * List current available access tokens
* Generate a new token from CLI `sip login auto` * Generate a new token from CLI `sip token create <token>`
* If `<token>` is present, add new access token, otherwise...
* Authenticate with username/password to get a new token without leaving the terminal * Authenticate with username/password to get a new token without leaving the terminal
* List available logins `sip login list` * Remove access tokens `sip tokens remove`
* Logout `sip logout`
* Remove user tokens
* Repository status `sip repo` * Repository status `sip repo`
* Get basic information about the `upstream` repository * Get basic information about the `upstream` repository
* Issue search `sip issues` * Issue search `sip issues`

@ -43,9 +43,9 @@ var (
Value: getUpstreamRepo()[2], Value: getUpstreamRepo()[2],
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "login", Name: "token",
Aliases: []string{"l"}, Aliases: []string{"t"},
Usage: "The login token to use (by name)", Usage: "The access token to use (by name)",
}, },
} }
originOnce sync.Once originOnce sync.Once
@ -55,38 +55,38 @@ var (
) )
func requireToken(ctx *cli.Context) (string, error) { func requireToken(ctx *cli.Context) (string, error) {
if ctx.IsSet("login") { if ctx.IsSet("token") {
return getToken(ctx.String("login")), nil return getToken(ctx.String("token")), nil
} }
loginMap := make(map[string]config.Login) tokenMap := make(map[string]config.Token)
opts := make([]string, len(config.Logins)) opts := make([]string, len(config.Tokens))
for idx, login := range config.Logins { for idx, token := range config.Tokens {
key := fmt.Sprintf("%s (%s)", login.Name, login.URL) key := fmt.Sprintf("%s (%s)", token.Name, token.URL)
loginMap[key] = login tokenMap[key] = token
opts[idx] = key opts[idx] = key
} }
question := &survey.Select{Message: "This action requires a login token", Options: opts} question := &survey.Select{Message: "This action requires an access token", Options: opts}
var answer string var answer string
if err := survey.AskOne(question, &answer); err != nil { if err := survey.AskOne(question, &answer); err != nil {
return "", err return "", err
} }
return loginMap[answer].Token, nil return tokenMap[answer].Token, nil
} }
func getToken(name string) string { func getToken(name string) string {
for _, login := range config.Logins { for _, token := range config.Tokens {
if name == login.Name { if name == token.Name {
return login.Token return token.Token
} }
} }
return "" return ""
} }
func getClient(ctx *cli.Context) *gitea.Client { func getClient(ctx *cli.Context) *gitea.Client {
return gitea.NewClient(ctx.String("url"), getToken(ctx.String("login"))) return gitea.NewClient(ctx.String("url"), getToken(ctx.String("token")))
} }
func getUpstreamRepo() []string { func getUpstreamRepo() []string {

@ -1,152 +0,0 @@
package cmd
import (
"code.gitea.io/sdk/gitea"
"errors"
"gitea.com/jolheiser/beaver"
"gitea.com/jolheiser/sip/modules/config"
"github.com/AlecAivazis/survey/v2"
"github.com/urfave/cli/v2"
)
var (
Login = cli.Command{
Name: "login",
Usage: "Log in to a Gitea server",
Action: doLogin,
Subcommands: []*cli.Command{
{
Name: "auto",
Usage: "Create a new token via API",
Action: doLoginAuto,
},
{
Name: "list",
Usage: "List available tokens",
Action: doLoginList,
},
},
}
)
func doLogin(ctx *cli.Context) error {
questions := []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "Name for this login"},
Validate: validateLoginName,
},
{
Name: "url",
Prompt: &survey.Input{Message: "URL for the Gitea instance", Default: ctx.String("url")},
Validate: survey.Required,
},
{
Name: "token",
Prompt: &survey.Input{Message: "API Token"},
Validate: survey.Required,
},
}
answers := struct {
Name string
URL string
Token string
}{}
if err := survey.Ask(questions, &answers); err != nil {
return err
}
config.Logins = append(config.Logins, config.Login{
Name: answers.Name,
URL: answers.URL,
Token: answers.Token,
})
if err := config.Save(); err != nil {
return err
}
beaver.Infof("Login saved! You can refer to it by using `--login %s` with commands!", answers.Name)
return nil
}
func doLoginAuto(ctx *cli.Context) error {
questions := []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "Name for this login", Default: "gitea"},
Validate: validateLoginName,
},
{
Name: "token",
Prompt: &survey.Input{Message: "Name for this token", Default: "sip"},
Validate: survey.Required,
},
{
Name: "url",
Prompt: &survey.Input{Message: "URL for the Gitea instance", Default: ctx.String("url")},
Validate: survey.Required,
},
{
Name: "username",
Prompt: &survey.Input{Message: "Username the Gitea instance"},
Validate: survey.Required,
},
{
Name: "password",
Prompt: &survey.Password{Message: "Password for the Gitea instance"},
Validate: survey.Required,
},
}
answers := struct {
Name string
Token string
URL string
Username string
Password string
}{}
if err := survey.Ask(questions, &answers); err != nil {
return err
}
client := gitea.NewClient(answers.URL, "")
token, err := client.CreateAccessToken(answers.Username, answers.Password, gitea.CreateAccessTokenOption{Name: answers.Token})
if err != nil {
return err
}
config.Logins = append(config.Logins, config.Login{
Name: answers.Name,
URL: answers.URL,
Token: token.Token,
})
if err := config.Save(); err != nil {
return err
}
beaver.Infof("Login saved! You can refer to it by using `--login %s` with commands!", answers.Name)
return nil
}
func doLoginList(ctx *cli.Context) error {
for idx, login := range config.Logins {
beaver.Infof("%d. %s (%s)", idx+1, login.Name, login.URL)
}
return nil
}
func validateLoginName(ans interface{}) error {
name := ans.(string)
for _, login := range config.Logins {
if name == login.Name {
return errors.New("login name already exists")
}
}
return survey.Required(ans)
}

25
cmd/token.go Normal file

@ -0,0 +1,25 @@
package cmd
import (
"gitea.com/jolheiser/beaver"
"gitea.com/jolheiser/sip/modules/config"
"github.com/urfave/cli/v2"
)
var Tokens = cli.Command{
Name: "tokens",
Aliases: []string{"token"},
Usage: "Manage access tokens",
Action: doTokenList,
Subcommands: []*cli.Command{
&TokensAdd,
&TokensRemove,
},
}
func doTokenList(ctx *cli.Context) error {
for idx, token := range config.Tokens {
beaver.Infof("%d. %s (%s)", idx+1, token.Name, token.URL)
}
return nil
}

101
cmd/token_add.go Normal file

@ -0,0 +1,101 @@
package cmd
import (
"code.gitea.io/sdk/gitea"
"errors"
"gitea.com/jolheiser/beaver"
"gitea.com/jolheiser/sip/modules/config"
"github.com/AlecAivazis/survey/v2"
"github.com/urfave/cli/v2"
)
var TokensAdd = cli.Command{
Name: "add",
Usage: "Add a new access token",
Action: doTokenAdd,
}
func doTokenAdd(ctx *cli.Context) error {
token := ctx.Args().First()
questions := []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "Local nickname for this token", Default: "gitea"},
Validate: validateTokenName,
},
{
Name: "token",
Prompt: &survey.Input{Message: "Name for this token in Gitea", Default: "sip"},
Validate: survey.Required,
},
{
Name: "url",
Prompt: &survey.Input{Message: "URL for the Gitea instance", Default: ctx.String("url")},
Validate: survey.Required,
},
}
answers := struct {
Name string
Token string
URL string
}{}
if err := survey.Ask(questions, &answers); err != nil {
return err
}
if token == "" {
authQuestions := []*survey.Question{
{
Name: "username",
Prompt: &survey.Input{Message: "Username the Gitea instance"},
Validate: survey.Required,
},
{
Name: "password",
Prompt: &survey.Password{Message: "Password for the Gitea instance"},
Validate: survey.Required,
},
}
authAnswers := struct {
Username string
Password string
}{}
if err := survey.Ask(authQuestions, &authAnswers); err != nil {
return err
}
client := gitea.NewClient(answers.URL, "")
t, err := client.CreateAccessToken(authAnswers.Username, authAnswers.Password, gitea.CreateAccessTokenOption{Name: answers.Token})
if err != nil {
return err
}
token = t.Token
}
config.Tokens = append(config.Tokens, config.Token{
Name: answers.Name,
URL: answers.URL,
Token: token,
})
if err := config.Save(); err != nil {
return err
}
beaver.Infof("Token saved! You can refer to it by using `--token %s` with commands!", answers.Name)
return nil
}
func validateTokenName(ans interface{}) error {
name := ans.(string)
for _, token := range config.Tokens {
if name == token.Name {
return errors.New("token already exists")
}
}
return survey.Required(ans)
}

@ -8,18 +8,16 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
var ( var TokensRemove = cli.Command{
Logout = cli.Command{ Name: "remove",
Name: "logout", Usage: "Remove access tokens",
Usage: "Log out of a Gitea server", Action: doTokenRemove,
Action: doLogout, }
}
)
func doLogout(ctx *cli.Context) error { func doTokenRemove(ctx *cli.Context) error {
opts := make([]string, len(config.Logins)) opts := make([]string, len(config.Tokens))
for idx, login := range config.Logins { for idx, token := range config.Tokens {
opts[idx] = fmt.Sprintf("%s (%s)", login.Name, login.URL) opts[idx] = fmt.Sprintf("%s (%s)", token.Name, token.URL)
} }
question := &survey.MultiSelect{ question := &survey.MultiSelect{
Message: "Which would you like to remove?", Message: "Which would you like to remove?",
@ -34,22 +32,22 @@ func doLogout(ctx *cli.Context) error {
idxs := make([]int, len(answers)) idxs := make([]int, len(answers))
for idx, answer := range answers { for idx, answer := range answers {
for idy, login := range config.Logins { for idy, token := range config.Tokens {
if answer == fmt.Sprintf("%s (%s)", login.Name, login.URL) { if answer == fmt.Sprintf("%s (%s)", token.Name, token.URL) {
idxs[len(answers)-idx-1] = idy idxs[len(answers)-idx-1] = idy
} }
} }
} }
for _, idx := range idxs { for _, idx := range idxs {
config.Logins = append(config.Logins[:idx], config.Logins[idx+1:]...) config.Tokens = append(config.Tokens[:idx], config.Tokens[idx+1:]...)
} }
if err := config.Save(); err != nil { if err := config.Save(); err != nil {
return err return err
} }
beaver.Infof("Logged out of %d accounts! Remember to clean up your tokens!", len(answers)) beaver.Infof("Removed %d token(s)! Remember to clean up in Gitea if necessary!", len(answers))
return nil return nil
} }

@ -16,8 +16,7 @@ func main() {
app.Version = Version app.Version = Version
app.Commands = []*cli.Command{ app.Commands = []*cli.Command{
&cmd.Config, &cmd.Config,
&cmd.Login, &cmd.Tokens,
&cmd.Logout,
&cmd.Repo, &cmd.Repo,
&cmd.Issues, &cmd.Issues,
&cmd.Pulls, &cmd.Pulls,

@ -15,16 +15,16 @@ var (
Origin string Origin string
Upstream string Upstream string
Logins []Login Tokens []Token
) )
type config struct { type config struct {
Origin string `toml:"origin"` Origin string `toml:"origin"`
Upstream string `toml:"upstream"` Upstream string `toml:"upstream"`
Logins []Login `toml:"login"` Tokens []Token `toml:"token"`
} }
type Login struct { type Token struct {
Name string `toml:"name"` Name string `toml:"name"`
URL string `toml:"url"` URL string `toml:"url"`
Token string `toml:"token"` Token string `toml:"token"`
@ -53,13 +53,13 @@ func init() {
Origin = cfg.Origin Origin = cfg.Origin
Upstream = cfg.Upstream Upstream = cfg.Upstream
Logins = cfg.Logins Tokens = cfg.Tokens
} }
func Save() error { func Save() error {
cfg.Origin = Origin cfg.Origin = Origin
cfg.Upstream = Upstream cfg.Upstream = Upstream
cfg.Logins = Logins cfg.Tokens = Tokens
fi, err := os.Create(configPath) fi, err := os.Create(configPath)
if err != nil { if err != nil {