1
0
mirror of https://gitea.com/jolheiser/sip synced 2024-11-22 19:51:58 +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`
* Change the default `origin` remote name `sip config origin`
* Change the default `upstream` remote name `sip config upstrea`
* Login `sip login`
* Add a user token for API usage
* Generate a new token from CLI `sip login auto`
* Tokens `sip tokens`
* List current available access tokens
* 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
* List available logins `sip login list`
* Logout `sip logout`
* Remove user tokens
* Remove access tokens `sip tokens remove`
* Repository status `sip repo`
* Get basic information about the `upstream` repository
* Issue search `sip issues`

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

@ -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"
)
var (
Logout = cli.Command{
Name: "logout",
Usage: "Log out of a Gitea server",
Action: doLogout,
var TokensRemove = cli.Command{
Name: "remove",
Usage: "Remove access tokens",
Action: doTokenRemove,
}
)
func doLogout(ctx *cli.Context) error {
opts := make([]string, len(config.Logins))
for idx, login := range config.Logins {
opts[idx] = fmt.Sprintf("%s (%s)", login.Name, login.URL)
func doTokenRemove(ctx *cli.Context) error {
opts := make([]string, len(config.Tokens))
for idx, token := range config.Tokens {
opts[idx] = fmt.Sprintf("%s (%s)", token.Name, token.URL)
}
question := &survey.MultiSelect{
Message: "Which would you like to remove?",
@ -34,22 +32,22 @@ func doLogout(ctx *cli.Context) error {
idxs := make([]int, len(answers))
for idx, answer := range answers {
for idy, login := range config.Logins {
if answer == fmt.Sprintf("%s (%s)", login.Name, login.URL) {
for idy, token := range config.Tokens {
if answer == fmt.Sprintf("%s (%s)", token.Name, token.URL) {
idxs[len(answers)-idx-1] = idy
}
}
}
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 {
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
}

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

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