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:
parent
b0816086dd
commit
039c227402
11
README.md
11
README.md
@ -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`
|
||||||
|
32
cmd/cmd.go
32
cmd/cmd.go
@ -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 {
|
||||||
|
152
cmd/login.go
152
cmd/login.go
@ -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
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
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
|
||||||
}
|
}
|
3
main.go
3
main.go
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user