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}