feat(secrets): FileStore.Delete to purge a user's OAuth tokens
Account disconnect/delete needs to remove the per-user YouTube refresh token from the SecretStore. Add Delete(ref) on the file-backed store, mirroring Put: atomic temp-file+rename, 0600, no-op on an absent ref. Kept off the read-only ports.SecretStore (Get) — write/delete follow the existing auth.TokenWriter convention of narrow capability interfaces, so the youtube adapter's read-only dependency is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -89,6 +89,43 @@ func (s *FileStore) Put(ref, value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes the secret stored under ref, persisting the file atomically
|
||||
// (temp file + rename) with 0600 permissions. Deleting an absent ref — or one in
|
||||
// a file that does not exist yet — is a no-op, not an error. Used by account
|
||||
// management (disconnect / delete-account) to purge a user's OAuth tokens.
|
||||
func (s *FileStore) Delete(ref string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
m, err := s.load()
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil // nothing to delete
|
||||
}
|
||||
return err
|
||||
}
|
||||
if _, ok := m[ref]; !ok {
|
||||
return nil // already absent
|
||||
}
|
||||
delete(m, ref)
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(s.path), 0o700); err != nil {
|
||||
return fmt.Errorf("secrets: create dir: %w", err)
|
||||
}
|
||||
b, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("secrets: marshal: %w", err)
|
||||
}
|
||||
tmp := s.path + ".tmp"
|
||||
if err := os.WriteFile(tmp, b, 0o600); err != nil {
|
||||
return fmt.Errorf("secrets: write temp: %w", err)
|
||||
}
|
||||
if err := os.Rename(tmp, s.path); err != nil {
|
||||
return fmt.Errorf("secrets: rename: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// load reads the backing file. A missing file yields an empty map (not an
|
||||
// error) for Get's caller, except Put distinguishes os.ErrNotExist.
|
||||
func (s *FileStore) load() (map[string]string, error) {
|
||||
|
||||
Reference in New Issue
Block a user