token.go

  1package core
  2
  3import (
  4	"fmt"
  5	"regexp"
  6	"strings"
  7
  8	"github.com/MichaelMure/git-bug/repository"
  9)
 10
 11const (
 12	tokenConfigKeyPrefix = "git-bug.token"
 13	tokenKeyValue        = "value"
 14	tokenKeyTarget       = "target"
 15	tokenKeyScopes       = "scopes"
 16)
 17
 18// Token represent token related informations
 19type Token struct {
 20	Id     string
 21	Value  string
 22	Target string
 23	Global bool
 24	Scopes []string
 25}
 26
 27// NewToken instantiate a new token
 28func NewToken(id, value, target string, global bool, scopes []string) *Token {
 29	return &Token{
 30		Id:     id,
 31		Value:  value,
 32		Target: target,
 33		Global: global,
 34		Scopes: scopes,
 35	}
 36}
 37
 38// Validate ensure token important fields are valid
 39func (t *Token) Validate() error {
 40	if t.Id == "" {
 41		return fmt.Errorf("missing token id")
 42	}
 43	if t.Value == "" {
 44		return fmt.Errorf("missing token value")
 45	}
 46	if t.Target == "" {
 47		return fmt.Errorf("missing token target")
 48	}
 49	return nil
 50}
 51
 52func loadToken(repo repository.RepoConfig, id string, global bool) (*Token, error) {
 53	keyPrefix := fmt.Sprintf("git-bug.token.%s.", id)
 54	var pairs map[string]string
 55	var err error
 56
 57	// read token config pairs
 58	if global {
 59		pairs, err = repo.ReadGlobalConfigs(keyPrefix)
 60		if err != nil {
 61			return nil, err
 62		}
 63	} else {
 64		pairs, err = repo.ReadConfigs(keyPrefix)
 65		if err != nil {
 66			return nil, err
 67		}
 68	}
 69
 70	// trim key prefix
 71	result := make(Configuration, len(pairs))
 72	for key, value := range pairs {
 73		key := strings.TrimPrefix(key, keyPrefix)
 74		result[key] = value
 75	}
 76
 77	var ok bool
 78	token := &Token{Id: id, Global: global}
 79	token.Value, ok = result[tokenKeyValue]
 80	if !ok {
 81		return nil, fmt.Errorf("empty token value")
 82	}
 83
 84	token.Target, ok = result[tokenKeyTarget]
 85	if !ok {
 86		return nil, fmt.Errorf("empty token key")
 87	}
 88
 89	scopesString, ok := result[tokenKeyScopes]
 90	if !ok {
 91		return nil, fmt.Errorf("missing scopes config")
 92	}
 93
 94	token.Scopes = strings.Split(scopesString, ",")
 95	return token, nil
 96}
 97
 98// GetToken loads a token from repo config
 99func GetToken(repo repository.RepoConfig, id string) (*Token, error) {
100	return loadToken(repo, id, false)
101}
102
103// GetGlobalToken loads a token from the global config
104func GetGlobalToken(repo repository.RepoConfig, id string) (*Token, error) {
105	return loadToken(repo, id, true)
106}
107
108func listTokens(repo repository.RepoConfig, global bool) ([]string, error) {
109	var configs map[string]string
110	var err error
111	if global {
112		configs, err = repo.ReadGlobalConfigs(tokenConfigKeyPrefix + ".")
113		if err != nil {
114			return nil, err
115		}
116	} else {
117		configs, err = repo.ReadConfigs(tokenConfigKeyPrefix + ".")
118		if err != nil {
119			return nil, err
120		}
121	}
122
123	re, err := regexp.Compile(tokenConfigKeyPrefix + `.([^.]+)`)
124	if err != nil {
125		panic(err)
126	}
127
128	set := make(map[string]interface{})
129
130	for key := range configs {
131		res := re.FindStringSubmatch(key)
132
133		if res == nil {
134			continue
135		}
136
137		set[res[1]] = nil
138	}
139
140	result := make([]string, len(set))
141	i := 0
142	for key := range set {
143		result[i] = key
144		i++
145	}
146
147	return result, nil
148}
149
150// ListTokens return the list of stored tokens in the repo config
151func ListTokens(repo repository.RepoConfig) ([]string, error) {
152	return listTokens(repo, false)
153}
154
155// ListGlobalTokens return the list of stored tokens in the global config
156func ListGlobalTokens(repo repository.RepoConfig) ([]string, error) {
157	return listTokens(repo, true)
158}
159
160func storeToken(repo repository.RepoConfig, token *Token) error {
161	var store func(key, value string) error
162	if token.Global {
163		store = repo.StoreGlobalConfig
164	} else {
165		store = repo.StoreConfig
166	}
167
168	var err error
169	storeValueKey := fmt.Sprintf("git-bug.token.%s.%s", token.Id, tokenKeyValue)
170	err = store(storeValueKey, token.Value)
171	if err != nil {
172		return err
173	}
174
175	storeTargetKey := fmt.Sprintf("git-bug.token.%s.%s", token.Id, tokenKeyTarget)
176	err = store(storeTargetKey, token.Target)
177	if err != nil {
178		return err
179	}
180
181	storeScopesKey := fmt.Sprintf("git-bug.token.%s.%s", token.Id, tokenKeyScopes)
182	err = store(storeScopesKey, strings.Join(token.Scopes, ","))
183	if err != nil {
184		return err
185	}
186
187	return nil
188}
189
190// StoreToken stores a token in the repo config
191func StoreToken(repo repository.RepoConfig, token *Token) error {
192	return storeToken(repo, token)
193}
194
195// StoreGlobalToken stores a token in global config
196func StoreGlobalToken(repo repository.RepoConfig, token *Token) error {
197	return storeToken(repo, token)
198}
199
200// RemoveToken removes a token from the repo config
201func RemoveToken(repo repository.RepoConfig, id string) error {
202	keyPrefix := fmt.Sprintf("git-bug.token.%s", id)
203	return repo.RmConfigs(keyPrefix)
204}
205
206// RemoveGlobalToken removes a token from the repo config
207func RemoveGlobalToken(repo repository.RepoConfig, id string) error {
208	keyPrefix := fmt.Sprintf("git-bug.token.%s", id)
209	return repo.RmGlobalConfigs(keyPrefix)
210}