102 lines
2.7 KiB
Go
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)
|
|
}
|
|
}
|