package core import ( "fmt" "regexp" "strconv" "strings" "github.com/MichaelMure/git-bug/repository" ) const ( tokenConfigKeyPrefix = "git-bug.token" tokenKeyValue = "value" tokenKeyTarget = "target" tokenKeyGlobal = "global" tokenKeyScopes = "scopes" ) // Token represent token related informations type Token struct { Name string Value string Target string Global bool Scopes []string } // NewToken instantiate a new token func NewToken(name, value, target string, global bool, scopes []string) *Token { return &Token{ Name: name, Value: value, Target: target, Global: global, Scopes: scopes, } } // Validate ensure token important fields are valid func (t *Token) Validate() error { if t.Name == "" { return fmt.Errorf("missing token name") } if t.Value == "" { return fmt.Errorf("missing token value") } if t.Target == "" { return fmt.Errorf("missing token target") } return nil } func loadToken(repo repository.RepoConfig, name string, global bool) (*Token, error) { keyPrefix := fmt.Sprintf("git-bug.token.%s", name) var pairs map[string]string var err error // read token config pairs if global { pairs, err = repo.ReadGlobalConfigs(keyPrefix) if err != nil { return nil, err } } else { pairs, err = repo.ReadConfigs(keyPrefix) if err != nil { return nil, err } } // trim key prefix result := make(Configuration, len(pairs)) for key, value := range pairs { key := strings.TrimPrefix(key, keyPrefix) result[key] = value } var ok bool token := &Token{Name: name} token.Value, ok = result[tokenKeyValue] if !ok { return nil, fmt.Errorf("empty token value") } token.Target, ok = result[tokenKeyTarget] if !ok { return nil, fmt.Errorf("empty token key") } if g, ok := result[tokenKeyGlobal]; !ok { return nil, fmt.Errorf("empty token global") } else if g == "true" { token.Global = true } scopesString, ok := result[tokenKeyScopes] if !ok { return nil, fmt.Errorf("missing scopes config") } token.Scopes = strings.Split(scopesString, ",") return token, nil } // GetToken loads a token from repo config func GetToken(repo repository.RepoConfig, name string) (*Token, error) { return loadToken(repo, name, false) } // GetGlobalToken loads a token from the global config func GetGlobalToken(repo repository.RepoConfig, name string) (*Token, error) { return loadToken(repo, name, true) } func listTokens(repo repository.RepoConfig, global bool) ([]string, error) { var configs map[string]string var err error if global { configs, err = repo.ReadConfigs(tokenConfigKeyPrefix + ".") if err != nil { return nil, err } } else { configs, err = repo.ReadGlobalConfigs(tokenConfigKeyPrefix + ".") if err != nil { return nil, err } } re, err := regexp.Compile(tokenConfigKeyPrefix + `.([^.]+)`) if err != nil { panic(err) } set := make(map[string]interface{}) for key := range configs { res := re.FindStringSubmatch(key) if res == nil { continue } set[res[1]] = nil } result := make([]string, len(set)) i := 0 for key := range set { result[i] = key i++ } 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) } // ListGlobalTokens return the list of stored tokens in the global config func ListGlobalTokens(repo repository.RepoConfig) ([]string, error) { return listTokens(repo, true) } func storeToken(repo repository.RepoConfig, token *Token) error { var store func(key, value string) error if token.Global { store = repo.StoreGlobalConfig } else { store = repo.StoreConfig } var err error storeValueKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyValue) err = store(storeValueKey, token.Value) if err != nil { return err } storeTargetKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyTarget) err = store(storeTargetKey, token.Target) if err != nil { return err } storeGlobalKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyGlobal) err = store(storeGlobalKey, strconv.FormatBool(token.Global)) if err != nil { return err } storeScopesKey := fmt.Sprintf("git-bug.token.%s.%s", token.Name, tokenKeyScopes) err = store(storeScopesKey, strings.Join(token.Scopes, ",")) if err != nil { return err } return nil } // StoreToken stores a token in the repo config func StoreToken(repo repository.RepoConfig, name, value, target string, scopes []string) error { return storeToken(repo, NewToken(name, value, target, false, scopes)) } // StoreGlobalToken stores a token in global config func StoreGlobalToken(repo repository.RepoConfig, name, value, target string, scopes []string) error { return storeToken(repo, NewToken(name, value, target, true, scopes)) } // RemoveToken removes a token from the repo config func RemoveToken(repo repository.RepoConfig, name string) error { keyPrefix := fmt.Sprintf("git-bug.token.%s", name) return repo.RmConfigs(keyPrefix) } // RemoveGlobalToken removes a token from the repo config func RemoveGlobalToken(repo repository.RepoConfig, name string) error { keyPrefix := fmt.Sprintf("git-bug.token.%s", name) return repo.RmGlobalConfigs(keyPrefix) }