// tokens.go package main import ( "crypto/rand" "encoding/base64" "encoding/json" "os" ) type TokenConfig struct { Token string `json:"token"` // raw token; in real life you want a hash Name string `json:"name"` // internal name ("jeff", etc.) Revoked bool `json:"revoked,omitempty"` } func loadTokens(path string) (map[string]*TokenConfig, error) { f, err := os.Open(path) if err != nil { return nil, err } defer f.Close() var list []TokenConfig if err := json.NewDecoder(f).Decode(&list); err != nil { return nil, err } m := make(map[string]*TokenConfig) for i := range list { tc := list[i] m[tc.Token] = &tc } return m, nil } func saveTokens(path string, tokens map[string]*TokenConfig) error { f, err := os.Create(path) if err != nil { return err } defer f.Close() enc := json.NewEncoder(f) enc.SetIndent("", " ") var list []TokenConfig for _, tc := range tokens { list = append(list, *tc) } return enc.Encode(list) } func generateToken() (string, error) { b := make([]byte, 32) if _, err := rand.Read(b); err != nil { return "", err } return "brg_" + base64.RawURLEncoding.EncodeToString(b), nil }