nub/internal/permission/policy_test.go
Tom a97013d876 initial commit
- v 0.1.0 siehe CHANGELOG.md
2026-07-25 11:08:01 +02:00

102 lines
2.7 KiB
Go

package permission
import (
"encoding/json"
"testing"
)
func input(t *testing.T, v any) json.RawMessage {
t.Helper()
b, err := json.Marshal(v)
if err != nil {
t.Fatal(err)
}
return b
}
func TestModeFor_UnknownToolDefaultsToAuto(t *testing.T) {
p := &Policy{Modes: map[string]Mode{"edit": ModeAsk}}
if got := p.ModeFor("github__create_issue"); got != ModeAuto {
t.Errorf("ModeFor(unknown) = %q, want auto", got)
}
}
func TestModeFor_NilPolicyDefaultsToAuto(t *testing.T) {
var p *Policy
if got := p.ModeFor("edit"); got != ModeAuto {
t.Errorf("ModeFor on nil policy = %q, want auto", got)
}
}
func TestModeFor_UsesConfiguredMode(t *testing.T) {
p := &Policy{Modes: map[string]Mode{"edit": ModeAsk, "bash": ModeDeny}}
if got := p.ModeFor("edit"); got != ModeAsk {
t.Errorf("edit = %q, want ask", got)
}
if got := p.ModeFor("bash"); got != ModeDeny {
t.Errorf("bash = %q, want deny", got)
}
}
func TestCheck_DenyPathOverridesAutoMode(t *testing.T) {
p := &Policy{
Modes: map[string]Mode{"edit": ModeAuto},
DenyPaths: []string{".git/**", "**/.env", "**/id_rsa*"},
}
cases := []struct {
path string
want Mode
}{
{".git/config", ModeDeny},
{".env", ModeDeny},
{"sub/.env", ModeDeny},
{"id_rsa", ModeDeny},
{"~/.ssh/id_rsa_backup", ModeDeny}, // "**/id_rsa*" matcht auch mit Verzeichnis-Präfix
{"main.go", ModeAuto},
}
for _, c := range cases {
got := p.Check("edit", input(t, map[string]string{"path": c.path}))
if got != c.want {
t.Errorf("Check(edit, path=%q) = %q, want %q", c.path, got, c.want)
}
}
}
func TestCheck_DenyBashOverridesAutoMode(t *testing.T) {
p := &Policy{
Modes: map[string]Mode{"bash": ModeAuto},
DenyBash: []string{"rm -rf /", "git push --force*"},
}
cases := []struct {
cmd string
want Mode
}{
{"rm -rf /", ModeDeny},
{"cd /tmp && rm -rf / --no-preserve-root", ModeDeny},
{"git push --force origin main", ModeDeny},
{"git status", ModeAuto},
}
for _, c := range cases {
got := p.Check("bash", input(t, map[string]string{"command": c.cmd}))
if got != c.want {
t.Errorf("Check(bash, command=%q) = %q, want %q", c.cmd, got, c.want)
}
}
}
func TestCheck_NonPathToolIgnoresDenyPaths(t *testing.T) {
p := &Policy{DenyPaths: []string{"**/.env"}}
// todo hat kein "path"-Feld -> DenyPaths darf nicht versehentlich greifen.
got := p.Check("todo", input(t, map[string]any{"items": []any{}}))
if got != ModeAuto {
t.Errorf("Check(todo) = %q, want auto (no path field to match against)", got)
}
}
func TestCheck_AskModePreservedWithoutDenyMatch(t *testing.T) {
p := &Policy{Modes: map[string]Mode{"edit": ModeAsk}}
got := p.Check("edit", input(t, map[string]string{"path": "main.go"}))
if got != ModeAsk {
t.Errorf("Check(edit) = %q, want ask", got)
}
}