diff --git a/pkg/tools/permission.go b/pkg/tools/permission.go new file mode 100644 index 000000000..073448f4e --- /dev/null +++ b/pkg/tools/permission.go @@ -0,0 +1,48 @@ +package tools + +import ( + "sync" +) + +type PermissionCache struct { + mu sync.RWMutex + perms map[string]string // path → "once"|"session"|"denied" +} + +func NewPermissionCache() *PermissionCache { + return &PermissionCache{ + perms: make(map[string]string), + } +} + +// Check returns "once", "session", "denied", or "" (no permission) +func (pc *PermissionCache) Check(path string) string { + pc.mu.RLock() + defer pc.mu.RUnlock() + + // Check exact match + if val, ok := pc.perms[path]; ok { + return val + } + + // Check if any parent path is granted "session" + for cachedPath, val := range pc.perms { + if val == "session" && len(cachedPath) < len(path) && path[:len(cachedPath)] == cachedPath { + return "session" + } + } + + return "" +} + +func (pc *PermissionCache) Grant(path, duration string) { + pc.mu.Lock() + defer pc.mu.Unlock() + pc.perms[path] = duration +} + +func (pc *PermissionCache) Revoke(path string) { + pc.mu.Lock() + defer pc.mu.Unlock() + delete(pc.perms, path) +} diff --git a/pkg/tools/permission_test.go b/pkg/tools/permission_test.go new file mode 100644 index 000000000..367072b2a --- /dev/null +++ b/pkg/tools/permission_test.go @@ -0,0 +1,13 @@ +package tools + +import ( + "testing" +) + +func TestPermissionCache_Check_NoPermission(t *testing.T) { + pc := NewPermissionCache() + result := pc.Check("/desktop") + if result != "" { + t.Errorf("Expected empty string, got %s", result) + } +}