token.go

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