commands/token/revoke/revoke.go (183 lines of code) (raw):

package revoke import ( "encoding/json" "errors" "fmt" "strconv" "gitlab.com/gitlab-org/cli/commands/token/filter" "gitlab.com/gitlab-org/cli/commands/flag" "gitlab.com/gitlab-org/cli/pkg/iostreams" "github.com/MakeNowJust/heredoc/v2" "github.com/spf13/cobra" gitlab "gitlab.com/gitlab-org/api/client-go" "gitlab.com/gitlab-org/cli/api" "gitlab.com/gitlab-org/cli/commands/cmdutils" "gitlab.com/gitlab-org/cli/internal/glrepo" ) type RevokeOptions struct { HTTPClient func() (*gitlab.Client, error) IO *iostreams.IOStreams BaseRepo func() (glrepo.Interface, error) User string Group string Name string TokenId int OutputFormat string } func NewCmdRevoke(f *cmdutils.Factory, runE func(opts *RevokeOptions) error) *cobra.Command { opts := &RevokeOptions{ IO: f.IO, } cmd := &cobra.Command{ Use: "revoke <token-name|token-id>", Short: "Revoke user, group or project access tokens", Aliases: []string{"revoke", "rm"}, Args: cobra.RangeArgs(1, 1), Long: heredoc.Doc(` Revoke an user, group or project access token. If multiple tokens with the same name exist, you can specify the ID of the token. The output format can be either "JSON" or "text". The JSON output will show the meta information of the revoked token. The normal text output is a description of the revoked token name and ID. Administrators can revoke personal access tokens belonging to other users. `), Example: heredoc.Doc(` Revoke a project access token of current project - glab token revoke my-project-token Revoke a project access token of a specific project - glab token revoke --repo user/my-repo my-project-token Revoke a group access token - glab token revoke --group group/sub-group my-group-token Revoke my personal access token - glab token revoke --user @me my-personal-token Revoke a personal access token of another user (administrator only) - glab token revoke --user johndoe johns-personal-token `), RunE: func(cmd *cobra.Command, args []string) (err error) { // Supports repo override opts.HTTPClient = f.HttpClient opts.BaseRepo = f.BaseRepo if opts.TokenId, err = strconv.Atoi(args[0]); err != nil { opts.Name = args[0] } if opts.Group, err = flag.GroupOverride(cmd); err != nil { return } if opts.Group != "" && opts.User != "" { return cmdutils.FlagError{Err: errors.New("'--group' and '--user' are mutually exclusive.")} } if runE != nil { return runE(opts) } return revokeTokenRun(opts) }, } cmdutils.EnableRepoOverride(cmd, f) cmd.Flags().StringVarP(&opts.Group, "group", "g", "", "Revoke group access token. Ignored if a user or repository argument is set.") cmd.Flags().StringVarP(&opts.User, "user", "U", "", "Revoke personal access token. Use @me for the current user.") cmd.Flags().StringVarP(&opts.OutputFormat, "output", "F", "text", "Format output as: text, json. 'text' provides the name and ID of the revoked token; 'json' outputs the token with metadata.") return cmd } func revokeTokenRun(opts *RevokeOptions) error { httpClient, err := opts.HTTPClient() if err != nil { return err } var outputToken any var outputTokenValue string if opts.User != "" { user, err := api.UserByName(httpClient, opts.User) if err != nil { return cmdutils.FlagError{Err: err} } options := &gitlab.ListPersonalAccessTokensOptions{ ListOptions: gitlab.ListOptions{PerPage: 100}, UserID: &user.ID, } tokens, err := api.ListPersonalAccessTokens(httpClient, options) if err != nil { return err } var token *gitlab.PersonalAccessToken tokens = filter.Filter(tokens, func(t *gitlab.PersonalAccessToken) bool { return t.Active && (t.Name == opts.Name || t.ID == opts.TokenId) }) switch len(tokens) { case 1: token = tokens[0] case 0: return cmdutils.FlagError{Err: fmt.Errorf("no token found with the name '%v'.", opts.Name)} default: return cmdutils.FlagError{Err: fmt.Errorf("multiple tokens found with the name '%v'. Use the ID instead.", opts.Name)} } if err = api.RevokePersonalAccessToken(httpClient, token.ID); err != nil { return err } token.Revoked = true outputToken = token outputTokenValue = fmt.Sprintf("revoked %s %s %d", opts.User, token.Name, token.ID) } else { if opts.Group != "" { options := &gitlab.ListGroupAccessTokensOptions{PerPage: 100} tokens, err := api.ListGroupAccessTokens(httpClient, opts.Group, options) if err != nil { return err } var token *gitlab.GroupAccessToken tokens = filter.Filter(tokens, func(t *gitlab.GroupAccessToken) bool { return t.Active && (t.Name == opts.Name || t.ID == opts.TokenId) }) switch len(tokens) { case 1: token = tokens[0] case 0: return cmdutils.FlagError{Err: fmt.Errorf("no token found with the name '%v'.", opts.Name)} default: return cmdutils.FlagError{Err: fmt.Errorf("multiple tokens found with the name '%v'. Use the ID instead.", opts.Name)} } if err = api.RevokeGroupAccessToken(httpClient, opts.Group, token.ID); err != nil { return err } token.Revoked = true outputToken = token outputTokenValue = fmt.Sprintf("revoked %s %d", token.Name, token.ID) } else { repo, err := opts.BaseRepo() if err != nil { return err } options := &gitlab.ListProjectAccessTokensOptions{ListOptions: gitlab.ListOptions{PerPage: 100}} tokens, err := api.ListProjectAccessTokens(httpClient, repo.FullName(), options) if err != nil { return err } tokens = filter.Filter(tokens, func(t *gitlab.ProjectAccessToken) bool { return t.Active && (t.Name == opts.Name || t.ID == opts.TokenId) }) var token *gitlab.ProjectAccessToken switch len(tokens) { case 1: token = tokens[0] case 0: return cmdutils.FlagError{Err: fmt.Errorf("no token found with the name '%v'.", opts.Name)} default: return cmdutils.FlagError{Err: fmt.Errorf("multiple tokens found with the name '%v'. Use the ID instead.", opts.Name)} } if err = api.RevokeProjectAccessToken(httpClient, repo.FullName(), token.ID); err != nil { return err } token.Revoked = true outputToken = token outputTokenValue = fmt.Sprintf("revoked %s %d", token.Name, token.ID) } } if opts.OutputFormat == "json" { encoder := json.NewEncoder(opts.IO.StdOut) if err := encoder.Encode(outputToken); err != nil { return err } } else { if _, err := opts.IO.StdOut.Write([]byte(outputTokenValue)); err != nil { return err } } return nil }