diff options
author | amine <hilalyamine@gmail.com> | 2019-10-24 20:16:51 +0200 |
---|---|---|
committer | amine <hilalyamine@gmail.com> | 2019-11-09 13:26:52 +0100 |
commit | baefa687b582632cd9cc21b945bc074c833f5389 (patch) | |
tree | ae2d8a8e918409a0db7d6949177df3660745b09d | |
parent | 3984919a3df95b8ec203bcb82b66c9c2270579c7 (diff) | |
download | git-bug-baefa687b582632cd9cc21b945bc074c833f5389.tar.gz |
tokens: use a hash as token identifier instead of the token it self
-rw-r--r-- | bridge/core/token.go | 129 | ||||
-rw-r--r-- | commands/bridge_token.go | 71 | ||||
-rw-r--r-- | commands/bridge_token_add.go | 10 | ||||
-rw-r--r-- | commands/bridge_token_rm.go | 2 | ||||
-rw-r--r-- | doc/man/git-bug-bridge-token-add.1 | 41 | ||||
-rw-r--r-- | doc/man/git-bug-bridge-token-rm.1 | 29 | ||||
-rw-r--r-- | doc/man/git-bug-bridge-token.1 | 35 | ||||
-rw-r--r-- | doc/md/git-bug_bridge.md | 2 | ||||
-rw-r--r-- | doc/md/git-bug_bridge_token.md | 26 | ||||
-rw-r--r-- | doc/md/git-bug_bridge_token_add.md | 26 | ||||
-rw-r--r-- | doc/md/git-bug_bridge_token_rm.md | 22 | ||||
-rw-r--r-- | misc/powershell_completion/git-bug | 10 | ||||
-rw-r--r-- | misc/zsh_completion/git-bug | 6 |
13 files changed, 319 insertions, 90 deletions
diff --git a/bridge/core/token.go b/bridge/core/token.go index 89c70af2..bd97cd18 100644 --- a/bridge/core/token.go +++ b/bridge/core/token.go @@ -1,6 +1,8 @@ package core import ( + "crypto/sha256" + "encoding/json" "fmt" "regexp" "strings" @@ -10,12 +12,14 @@ import ( const ( tokenConfigKeyPrefix = "git-bug.token" - tokenKeyTarget = "target" - tokenKeyScopes = "scopes" + tokenValueKey = "value" + tokenTargetKey = "target" + tokenScopesKey = "scopes" ) // Token holds an API access token data type Token struct { + ID string Value string Target string Global bool @@ -24,16 +28,46 @@ type Token struct { // NewToken instantiate a new token func NewToken(value, target string, global bool, scopes []string) *Token { - return &Token{ + token := &Token{ Value: value, Target: target, Global: global, Scopes: scopes, } + + token.ID = hashToken(token) + return token +} + +// Id return full token identifier. It will compute the Id if it's empty +func (t *Token) Id() string { + if t.ID == "" { + t.ID = hashToken(t) + } + + return t.ID +} + +// HumanId return the truncated token id +func (t *Token) HumanId() string { + return t.Id()[:6] +} + +func hashToken(token *Token) string { + tokenJson, err := json.Marshal(&token) + if err != nil { + panic(err) + } + + sum := sha256.Sum256(tokenJson) + return fmt.Sprintf("%x", sum) } // Validate ensure token important fields are valid func (t *Token) Validate() error { + if t.ID == "" { + return fmt.Errorf("missing id") + } if t.Value == "" { return fmt.Errorf("missing value") } @@ -46,8 +80,17 @@ func (t *Token) Validate() error { return nil } -func loadToken(repo repository.RepoConfig, value string, global bool) (*Token, error) { - keyPrefix := fmt.Sprintf("git-bug.token.%s.", value) +// Kind return the type of the token as string +func (t *Token) Kind() string { + if t.Global { + return "global" + } + + return "local" +} + +func loadToken(repo repository.RepoConfig, id string, global bool) (*Token, error) { + keyPrefix := fmt.Sprintf("git-bug.token.%s.", id) readerFn := repo.ReadConfigs if global { @@ -62,19 +105,25 @@ func loadToken(repo repository.RepoConfig, value string, global bool) (*Token, e // trim key prefix for key, value := range configs { + delete(configs, key) newKey := strings.TrimPrefix(key, keyPrefix) configs[newKey] = value - delete(configs, key) } var ok bool - token := &Token{Value: value, Global: global} - token.Target, ok = configs[tokenKeyTarget] + token := &Token{ID: id, Global: global} + + token.Value, ok = configs[tokenValueKey] + if !ok { + return nil, fmt.Errorf("empty token value") + } + + token.Target, ok = configs[tokenTargetKey] if !ok { return nil, fmt.Errorf("empty token key") } - scopesString, ok := configs[tokenKeyScopes] + scopesString, ok := configs[tokenScopesKey] if !ok { return nil, fmt.Errorf("missing scopes config") } @@ -84,13 +133,13 @@ func loadToken(repo repository.RepoConfig, value string, global bool) (*Token, e } // GetToken loads a token from repo config -func GetToken(repo repository.RepoConfig, value string) (*Token, error) { - return loadToken(repo, value, false) +func GetToken(repo repository.RepoConfig, id string) (*Token, error) { + return loadToken(repo, id, false) } // GetGlobalToken loads a token from the global config -func GetGlobalToken(repo repository.RepoConfig, value string) (*Token, error) { - return loadToken(repo, value, true) +func GetGlobalToken(repo repository.RepoConfig, id string) (*Token, error) { + return loadToken(repo, id, true) } func listTokens(repo repository.RepoConfig, global bool) ([]string, error) { @@ -131,14 +180,29 @@ func listTokens(repo repository.RepoConfig, global bool) ([]string, error) { return result, nil } -// ListTokens return the list of stored tokens in the repo config -func ListTokens(repo repository.RepoConfig) ([]string, error) { - return listTokens(repo, false) -} +// ListTokens return a map representing the stored tokens in the repo config and global config +// along with their type (global: true, local:false) +func ListTokens(repo repository.RepoConfig) (map[string]bool, error) { + localTokens, err := listTokens(repo, false) + if err != nil { + return nil, err + } -// ListGlobalTokens return the list of stored tokens in the global config -func ListGlobalTokens(repo repository.RepoConfig) ([]string, error) { - return listTokens(repo, true) + globalTokens, err := listTokens(repo, true) + if err != nil { + return nil, err + } + + tokens := map[string]bool{} + for _, token := range localTokens { + tokens[token] = false + } + + for _, token := range globalTokens { + tokens[token] = true + } + + return tokens, nil } func storeToken(repo repository.RepoConfig, token *Token) error { @@ -147,13 +211,19 @@ func storeToken(repo repository.RepoConfig, token *Token) error { storeFn = repo.StoreGlobalConfig } - storeTargetKey := fmt.Sprintf("git-bug.token.%s.%s", token.Value, tokenKeyTarget) - err := storeFn(storeTargetKey, token.Target) + storeValueKey := fmt.Sprintf("git-bug.token.%s.%s", token.Id(), tokenValueKey) + err := storeFn(storeValueKey, token.Value) + if err != nil { + return err + } + + storeTargetKey := fmt.Sprintf("git-bug.token.%s.%s", token.Id(), tokenTargetKey) + err = storeFn(storeTargetKey, token.Target) if err != nil { return err } - storeScopesKey := fmt.Sprintf("git-bug.token.%s.%s", token.Value, tokenKeyScopes) + storeScopesKey := fmt.Sprintf("git-bug.token.%s.%s", token.Id(), tokenScopesKey) return storeFn(storeScopesKey, strings.Join(token.Scopes, ",")) } @@ -162,19 +232,14 @@ func StoreToken(repo repository.RepoConfig, token *Token) error { return storeToken(repo, token) } -// StoreGlobalToken stores a token in global config -func StoreGlobalToken(repo repository.RepoConfig, token *Token) error { - return storeToken(repo, token) -} - // RemoveToken removes a token from the repo config -func RemoveToken(repo repository.RepoConfig, value string) error { - keyPrefix := fmt.Sprintf("git-bug.token.%s", value) +func RemoveToken(repo repository.RepoConfig, id string) error { + keyPrefix := fmt.Sprintf("git-bug.token.%s", id) return repo.RmConfigs(keyPrefix) } // RemoveGlobalToken removes a token from the repo config -func RemoveGlobalToken(repo repository.RepoConfig, value string) error { - keyPrefix := fmt.Sprintf("git-bug.token.%s", value) +func RemoveGlobalToken(repo repository.RepoConfig, id string) error { + keyPrefix := fmt.Sprintf("git-bug.token.%s", id) return repo.RmGlobalConfigs(keyPrefix) } diff --git a/commands/bridge_token.go b/commands/bridge_token.go index cb9754c3..f33ee3e3 100644 --- a/commands/bridge_token.go +++ b/commands/bridge_token.go @@ -14,8 +14,8 @@ import ( ) var ( - bridgeTokenLocalOnly bool - bridgeTokenGlobalOnly bool + bridgeTokenLocal bool + bridgeTokenGlobal bool ) func runTokenBridge(cmd *cobra.Command, args []string) error { @@ -26,55 +26,46 @@ func runTokenBridge(cmd *cobra.Command, args []string) error { defer backend.Close() interrupt.RegisterCleaner(backend.Close) - var tokens []*core.Token - if !bridgeTokenGlobalOnly { - localTokens, err := core.ListTokens(backend) - if err != nil { - return err - } + tokens, err := core.ListTokens(backend) + if err != nil { + return err + } - for _, id := range localTokens { - token, err := core.GetToken(repo, id) - if err != nil { - return err - } - tokens = append(tokens, token) + for token, global := range tokens { + // TODO: filter tokens using flags + getTokenFn := core.GetToken + if global { + getTokenFn = core.GetGlobalToken } - } - if !bridgeTokenLocalOnly { - globalTokens, err := core.ListGlobalTokens(backend) + token, err := getTokenFn(repo, token) if err != nil { return err } - - for _, id := range globalTokens { - token, err := core.GetGlobalToken(repo, id) - if err != nil { - return err - } - tokens = append(tokens, token) - } + printToken(token) } - for _, token := range tokens { - valueFmt := text.LeftPadMaxLine(token.Value, 20, 0) - targetFmt := text.LeftPadMaxLine(token.Target, 8, 0) - scopesFmt := text.LeftPadMaxLine(strings.Join(token.Scopes, ","), 20, 0) - - fmt.Printf("%s %s %s %s\n", - valueFmt, - colors.Magenta(targetFmt), - colors.Yellow(token.Global), - scopesFmt, - ) - } return nil } +func printToken(token *core.Token) { + idFmt := text.LeftPadMaxLine(token.HumanId(), 6, 0) + valueFmt := text.LeftPadMaxLine(token.Value, 8, 0) + targetFmt := text.LeftPadMaxLine(token.Target, 8, 0) + scopesFmt := text.LeftPadMaxLine(strings.Join(token.Scopes, ","), 20, 0) + + fmt.Printf("%s %s %s %s %s\n", + idFmt, + valueFmt, + colors.Magenta(targetFmt), + colors.Yellow(token.Kind()), + scopesFmt, + ) +} + var bridgeTokenCmd = &cobra.Command{ Use: "token", - Short: "Configure and use bridge tokens.", + Short: "List all stored tokens.", PreRunE: loadRepo, RunE: runTokenBridge, Args: cobra.NoArgs, @@ -82,7 +73,7 @@ var bridgeTokenCmd = &cobra.Command{ func init() { bridgeCmd.AddCommand(bridgeTokenCmd) - bridgeTokenCmd.Flags().BoolVarP(&bridgeTokenLocalOnly, "local", "l", false, "") - bridgeTokenCmd.Flags().BoolVarP(&bridgeTokenGlobalOnly, "global", "g", false, "") + bridgeTokenCmd.Flags().BoolVarP(&bridgeTokenLocal, "local", "l", false, "") + bridgeTokenCmd.Flags().BoolVarP(&bridgeTokenGlobal, "global", "g", false, "") bridgeTokenCmd.Flags().SortFlags = false } diff --git a/commands/bridge_token_add.go b/commands/bridge_token_add.go index 76fed237..7b7a8964 100644 --- a/commands/bridge_token_add.go +++ b/commands/bridge_token_add.go @@ -12,20 +12,18 @@ var ( ) func runBridgeTokenAdd(cmd *cobra.Command, args []string) error { + _ = bridgeToken.Id() // TODO: a better design to avoid doing this + if err := bridgeToken.Validate(); err != nil { return errors.Wrap(err, "invalid token") } - if bridgeToken.Global { - return core.StoreToken(repo, &bridgeToken) - } - - return core.StoreGlobalToken(repo, &bridgeToken) + return core.StoreToken(repo, &bridgeToken) } var bridgeTokenAddCmd = &cobra.Command{ Use: "add", - Short: "Configure and use bridge tokens.", + Short: "Create and store a new token", PreRunE: loadRepo, RunE: runBridgeTokenAdd, Args: cobra.NoArgs, diff --git a/commands/bridge_token_rm.go b/commands/bridge_token_rm.go index 7fd79126..29fdb4f2 100644 --- a/commands/bridge_token_rm.go +++ b/commands/bridge_token_rm.go @@ -18,7 +18,7 @@ func runBridgeTokenRm(cmd *cobra.Command, args []string) error { var bridgeTokenRmCmd = &cobra.Command{ Use: "rm", - Short: "Configure and use bridge tokens.", + Short: "Remove token by Id.", PreRunE: loadRepo, RunE: runBridgeTokenRm, Args: cobra.ExactArgs(1), diff --git a/doc/man/git-bug-bridge-token-add.1 b/doc/man/git-bug-bridge-token-add.1 new file mode 100644 index 00000000..1eb5bb20 --- /dev/null +++ b/doc/man/git-bug-bridge-token-add.1 @@ -0,0 +1,41 @@ +.TH "GIT-BUG" "1" "Apr 2019" "Generated from git-bug's source code" "" +.nh +.ad l + + +.SH NAME +.PP +git\-bug\-bridge\-token\-add \- Create and store a new token + + +.SH SYNOPSIS +.PP +\fBgit\-bug bridge token add [flags]\fP + + +.SH DESCRIPTION +.PP +Create and store a new token + + +.SH OPTIONS +.PP +\fB\-g\fP, \fB\-\-global\fP[=false] + +.PP +\fB\-v\fP, \fB\-\-value\fP="" + +.PP +\fB\-t\fP, \fB\-\-target\fP="" + +.PP +\fB\-s\fP, \fB\-\-scopes\fP=[] + +.PP +\fB\-h\fP, \fB\-\-help\fP[=false] + help for add + + +.SH SEE ALSO +.PP +\fBgit\-bug\-bridge\-token(1)\fP diff --git a/doc/man/git-bug-bridge-token-rm.1 b/doc/man/git-bug-bridge-token-rm.1 new file mode 100644 index 00000000..5c5a16a6 --- /dev/null +++ b/doc/man/git-bug-bridge-token-rm.1 @@ -0,0 +1,29 @@ +.TH "GIT-BUG" "1" "Apr 2019" "Generated from git-bug's source code" "" +.nh +.ad l + + +.SH NAME +.PP +git\-bug\-bridge\-token\-rm \- Remove token by Id. + + +.SH SYNOPSIS +.PP +\fBgit\-bug bridge token rm [flags]\fP + + +.SH DESCRIPTION +.PP +Remove token by Id. + + +.SH OPTIONS +.PP +\fB\-h\fP, \fB\-\-help\fP[=false] + help for rm + + +.SH SEE ALSO +.PP +\fBgit\-bug\-bridge\-token(1)\fP diff --git a/doc/man/git-bug-bridge-token.1 b/doc/man/git-bug-bridge-token.1 new file mode 100644 index 00000000..d97c8e33 --- /dev/null +++ b/doc/man/git-bug-bridge-token.1 @@ -0,0 +1,35 @@ +.TH "GIT-BUG" "1" "Apr 2019" "Generated from git-bug's source code" "" +.nh +.ad l + + +.SH NAME +.PP +git\-bug\-bridge\-token \- List all stored tokens. + + +.SH SYNOPSIS +.PP +\fBgit\-bug bridge token [flags]\fP + + +.SH DESCRIPTION +.PP +List all stored tokens. + + +.SH OPTIONS +.PP +\fB\-l\fP, \fB\-\-local\fP[=false] + +.PP +\fB\-g\fP, \fB\-\-global\fP[=false] + +.PP +\fB\-h\fP, \fB\-\-help\fP[=false] + help for token + + +.SH SEE ALSO +.PP +\fBgit\-bug\-bridge(1)\fP, \fBgit\-bug\-bridge\-token\-add(1)\fP, \fBgit\-bug\-bridge\-token\-rm(1)\fP diff --git a/doc/md/git-bug_bridge.md b/doc/md/git-bug_bridge.md index 7731ff4b..a965074d 100644 --- a/doc/md/git-bug_bridge.md +++ b/doc/md/git-bug_bridge.md @@ -23,5 +23,5 @@ git-bug bridge [flags] * [git-bug bridge pull](git-bug_bridge_pull.md) - Pull updates. * [git-bug bridge push](git-bug_bridge_push.md) - Push updates. * [git-bug bridge rm](git-bug_bridge_rm.md) - Delete a configured bridge. -* [git-bug bridge token](git-bug_bridge_token.md) - Configure and use bridge tokens. +* [git-bug bridge token](git-bug_bridge_token.md) - List all stored tokens. diff --git a/doc/md/git-bug_bridge_token.md b/doc/md/git-bug_bridge_token.md new file mode 100644 index 00000000..5e6baa26 --- /dev/null +++ b/doc/md/git-bug_bridge_token.md @@ -0,0 +1,26 @@ +## git-bug bridge token + +List all stored tokens. + +### Synopsis + +List all stored tokens. + +``` +git-bug bridge token [flags] +``` + +### Options + +``` + -l, --local + -g, --global + -h, --help help for token +``` + +### SEE ALSO + +* [git-bug bridge](git-bug_bridge.md) - Configure and use bridges to other bug trackers. +* [git-bug bridge token add](git-bug_bridge_token_add.md) - Create and store a new token +* [git-bug bridge token rm](git-bug_bridge_token_rm.md) - Remove token by Id. + diff --git a/doc/md/git-bug_bridge_token_add.md b/doc/md/git-bug_bridge_token_add.md new file mode 100644 index 00000000..6ef705d0 --- /dev/null +++ b/doc/md/git-bug_bridge_token_add.md @@ -0,0 +1,26 @@ +## git-bug bridge token add + +Create and store a new token + +### Synopsis + +Create and store a new token + +``` +git-bug bridge token add [flags] +``` + +### Options + +``` + -g, --global + -v, --value string + -t, --target string + -s, --scopes stringArray + -h, --help help for add +``` + +### SEE ALSO + +* [git-bug bridge token](git-bug_bridge_token.md) - List all stored tokens. + diff --git a/doc/md/git-bug_bridge_token_rm.md b/doc/md/git-bug_bridge_token_rm.md new file mode 100644 index 00000000..52417a9c --- /dev/null +++ b/doc/md/git-bug_bridge_token_rm.md @@ -0,0 +1,22 @@ +## git-bug bridge token rm + +Remove token by Id. + +### Synopsis + +Remove token by Id. + +``` +git-bug bridge token rm [flags] +``` + +### Options + +``` + -h, --help help for rm +``` + +### SEE ALSO + +* [git-bug bridge token](git-bug_bridge_token.md) - List all stored tokens. + diff --git a/misc/powershell_completion/git-bug b/misc/powershell_completion/git-bug index e875b8a2..d92bc04b 100644 --- a/misc/powershell_completion/git-bug +++ b/misc/powershell_completion/git-bug @@ -22,7 +22,6 @@ Register-ArgumentCompleter -Native -CommandName 'git-bug' -ScriptBlock { [CompletionResult]::new('commands', 'commands', [CompletionResultType]::ParameterValue, 'Display available commands.') [CompletionResult]::new('comment', 'comment', [CompletionResultType]::ParameterValue, 'Display or add comments to a bug.') [CompletionResult]::new('deselect', 'deselect', [CompletionResultType]::ParameterValue, 'Clear the implicitly selected bug.') - [CompletionResult]::new('export', 'export', [CompletionResultType]::ParameterValue, '') [CompletionResult]::new('label', 'label', [CompletionResultType]::ParameterValue, 'Display, add or remove labels to/from a bug.') [CompletionResult]::new('ls', 'ls', [CompletionResultType]::ParameterValue, 'List bugs.') [CompletionResult]::new('ls-id', 'ls-id', [CompletionResultType]::ParameterValue, 'List bug identifiers.') @@ -53,7 +52,7 @@ Register-ArgumentCompleter -Native -CommandName 'git-bug' -ScriptBlock { [CompletionResult]::new('pull', 'pull', [CompletionResultType]::ParameterValue, 'Pull updates.') [CompletionResult]::new('push', 'push', [CompletionResultType]::ParameterValue, 'Push updates.') [CompletionResult]::new('rm', 'rm', [CompletionResultType]::ParameterValue, 'Delete a configured bridge.') - [CompletionResult]::new('token', 'token', [CompletionResultType]::ParameterValue, 'Configure and use bridge tokens.') + [CompletionResult]::new('token', 'token', [CompletionResultType]::ParameterValue, 'List all stored tokens.') break } 'git-bug;bridge;configure' { @@ -90,8 +89,8 @@ Register-ArgumentCompleter -Native -CommandName 'git-bug' -ScriptBlock { [CompletionResult]::new('--local', 'local', [CompletionResultType]::ParameterName, '') [CompletionResult]::new('-g', 'g', [CompletionResultType]::ParameterName, '') [CompletionResult]::new('--global', 'global', [CompletionResultType]::ParameterName, '') - [CompletionResult]::new('add', 'add', [CompletionResultType]::ParameterValue, 'Configure and use bridge tokens.') - [CompletionResult]::new('rm', 'rm', [CompletionResultType]::ParameterValue, 'Configure and use bridge tokens.') + [CompletionResult]::new('add', 'add', [CompletionResultType]::ParameterValue, 'Create and store a new token') + [CompletionResult]::new('rm', 'rm', [CompletionResultType]::ParameterValue, 'Remove token by Id.') break } 'git-bug;bridge;token;add' { @@ -127,9 +126,6 @@ Register-ArgumentCompleter -Native -CommandName 'git-bug' -ScriptBlock { 'git-bug;deselect' { break } - 'git-bug;export' { - break - } 'git-bug;label' { [CompletionResult]::new('add', 'add', [CompletionResultType]::ParameterValue, 'Add a label to a bug.') [CompletionResult]::new('rm', 'rm', [CompletionResultType]::ParameterValue, 'Remove a label from a bug.') diff --git a/misc/zsh_completion/git-bug b/misc/zsh_completion/git-bug index 1f4679ad..d9da4ac2 100644 --- a/misc/zsh_completion/git-bug +++ b/misc/zsh_completion/git-bug @@ -118,7 +118,7 @@ function _git-bug_bridge { "pull:Pull updates." "push:Push updates." "rm:Delete a configured bridge." - "token:Configure and use bridge tokens." + "token:List all stored tokens." ) _describe "command" commands ;; @@ -181,8 +181,8 @@ function _git-bug_bridge_token { case $state in cmnds) commands=( - "add:Configure and use bridge tokens." - "rm:Configure and use bridge tokens." + "add:Create and store a new token" + "rm:Remove token by Id." ) _describe "command" commands ;; |