github.com/benchkram/bob@v0.0.0-20240314204020-b7a57f2f9be9/pkg/auth/store.go (about) 1 package auth 2 3 import ( 4 "errors" 5 "os" 6 "path" 7 8 "github.com/benchkram/errz" 9 "gopkg.in/yaml.v3" 10 ) 11 12 var ( 13 ErrNotFound = errors.New("not found") 14 ErrAlreadyExists = errors.New("already exists") 15 ) 16 17 type Store struct { 18 dir string 19 configPath string 20 } 21 22 type YamlAuthContext struct { 23 Name string `yaml:"name"` 24 Token string `yaml:"token"` 25 Current bool `yaml:"current"` 26 } 27 28 // New creates a filestore. The caller is responsible to pass an 29 // existing directory. 30 func New(dir string) *Store { 31 s := &Store{ 32 dir: dir, 33 configPath: path.Join(dir, "auth.yaml"), 34 } 35 36 return s 37 } 38 39 func (s *Store) Contexts() (names []Context, err error) { 40 defer errz.Recover(&err) 41 42 ctxs, err := s.contexts() 43 errz.Fatal(err) 44 45 names = []Context{} 46 for _, c := range ctxs { 47 names = append(names, Context{ 48 Name: c.Name, 49 Token: c.Token, 50 Current: c.Current, 51 }) 52 } 53 54 return names, nil 55 } 56 57 func (s *Store) Context(name string) (ctx Context, err error) { 58 defer errz.Recover(&err) 59 60 ctxs, err := s.contexts() 61 errz.Fatal(err) 62 63 for _, c := range ctxs { 64 if c.Name == name { 65 return Context{ 66 Name: c.Name, 67 Token: c.Token, 68 }, nil 69 } 70 } 71 72 errz.Fatal(ErrNotFound) 73 return 74 } 75 76 func (s *Store) CreateContext(name, token string) (err error) { 77 defer errz.Recover(&err) 78 79 ctxs, err := s.contexts() 80 errz.Fatal(err) 81 82 var exists bool 83 for _, c := range ctxs { 84 if c.Name == name { 85 exists = true 86 break 87 } 88 } 89 90 if exists { 91 errz.Fatal(ErrAlreadyExists) 92 } 93 94 ctxs = append(ctxs, &YamlAuthContext{ 95 Name: name, 96 Token: token, 97 Current: len(ctxs) == 0, 98 }) 99 100 return s.save(ctxs) 101 } 102 func (s *Store) DeleteContext(name string) (err error) { 103 defer errz.Recover(&err) 104 105 ctxs, err := s.contexts() 106 errz.Fatal(err) 107 108 var found bool 109 for i, c := range ctxs { 110 if c.Name == name { 111 found = true 112 113 // remove this context 114 ctxs = append(ctxs[:i], ctxs[i+1:]...) 115 if c.Current && len(ctxs) > 0 { 116 // mark the next context as current (if any left) 117 ctxs[len(ctxs)-1].Current = true 118 } 119 120 break 121 } 122 } 123 124 if !found { 125 errz.Fatal(ErrNotFound) 126 } 127 128 return s.save(ctxs) 129 } 130 131 func (s *Store) CurrentContext() (c Context, err error) { 132 defer errz.Recover(&err) 133 134 ctxs, err := s.contexts() 135 errz.Fatal(err) 136 137 for _, c := range ctxs { 138 if c.Current { 139 return Context{ 140 Name: c.Name, 141 Token: c.Token, 142 }, nil 143 } 144 } 145 146 return Context{}, ErrNotFound 147 } 148 149 func (s *Store) SetCurrentContext(name string) (err error) { 150 defer errz.Recover(&err) 151 152 ctxs, err := s.contexts() 153 errz.Fatal(err) 154 155 var exists bool 156 for _, c := range ctxs { 157 if c.Name == name { 158 exists = true 159 } 160 } 161 162 if !exists { 163 errz.Fatal(ErrNotFound) 164 } 165 166 for _, c := range ctxs { 167 if c.Name == name { 168 c.Current = true 169 } else { 170 c.Current = false 171 } 172 } 173 174 return s.save(ctxs) 175 } 176 177 func (s *Store) UpdateContext(name, token string) (err error) { 178 defer errz.Recover(&err) 179 180 ctxs, err := s.contexts() 181 errz.Fatal(err) 182 183 var found bool 184 for _, c := range ctxs { 185 if c.Name == name { 186 c.Token = token 187 found = true 188 break 189 } 190 } 191 192 if !found { 193 errz.Fatal(ErrNotFound) 194 } 195 196 return s.save(ctxs) 197 } 198 199 func (s *Store) contexts() (ctxs []*YamlAuthContext, err error) { 200 defer errz.Recover(&err) 201 202 b, err := os.ReadFile(path.Join(s.dir, "auth.yaml")) 203 if errors.Is(err, os.ErrNotExist) { 204 return []*YamlAuthContext{}, nil 205 } 206 errz.Fatal(err) 207 208 err = yaml.Unmarshal(b, &ctxs) 209 errz.Fatal(err) 210 211 return ctxs, nil 212 } 213 214 func (s *Store) save(ctxs []*YamlAuthContext) (err error) { 215 defer errz.Recover(&err) 216 217 b, err := yaml.Marshal(ctxs) 218 errz.Fatal(err) 219 220 err = os.WriteFile(s.configPath, b, os.ModePerm) 221 errz.Fatal(err) 222 223 return nil 224 }