package workspace import ( "encoding/json" "fmt" "strings" "go.etcd.io/bbolt" ) type TokenPermission int const ( TokenFile = 1 << iota TokenRedirect ) type Token struct { Key string Permission TokenPermission Description string } func (t Token) Has(perm TokenPermission) bool { return t.Permission&perm != 0 } func ParseTokenPermission(s string) (TokenPermission, error) { switch strings.ToLower(s) { case "a", "all": return TokenRedirect | TokenFile, nil case "r", "redirect": return TokenRedirect, nil case "f", "file": return TokenFile, nil default: return 0, fmt.Errorf("%q did not match a token permission", s) } } func (t TokenPermission) String() string { switch t { case TokenRedirect | TokenFile: return "all" case TokenRedirect: return "redirect" case TokenFile: return "file" default: return "unknown" } } func (w *Workspace) Token(key string) (token Token, err error) { return token, w.db.View(func(tx *bbolt.Tx) error { data := tx.Bucket(tokenBucket).Get([]byte(key)) return json.Unmarshal(data, &token) }) } func (w *Workspace) Tokens() ([]Token, error) { var tokens []Token return tokens, w.db.View(func(tx *bbolt.Tx) error { return tx.Bucket(tokenBucket).ForEach(func(_, v []byte) error { var token Token if err := json.Unmarshal(v, &token); err != nil { return err } tokens = append(tokens, token) return nil }) }) } func (w *Workspace) AddToken(token Token) error { return w.db.Update(func(tx *bbolt.Tx) error { data, err := json.Marshal(token) if err != nil { return err } return tx.Bucket(tokenBucket).Put([]byte(token.Key), data) }) } func (w *Workspace) DeleteTokens(keys ...string) error { return w.db.Update(func(tx *bbolt.Tx) error { var failed []string for _, key := range keys { if err := tx.Bucket(tokenBucket).Delete([]byte(key)); err != nil { failed = append(failed, key) } } if len(failed) != 0 { return fmt.Errorf("failed to delete %d tokens: %s", len(failed), failed) } return nil }) }