package restrict import ( "context" "testing" "git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry" ) // toolStub is a mock Tool used only to register a capability by name. type toolStub struct{ name string } func (t toolStub) Name() string { return t.name } func (t toolStub) Description() string { return "desc " + t.name } func (t toolStub) Parameters() (map[string]any, error) { return map[string]any{}, nil } func (t toolStub) Execute(_ context.Context, _ any) (any, error) { return nil, nil } func mustRegTool(t *testing.T, r *registry.Registry, name string) { t.Helper() if err := r.RegisterTool(toolStub{name: name}); err != nil { t.Fatalf("RegisterTool(%s): %v", name, err) } } func TestSetContext_OwnerAllowsAll(t *testing.T) { t.Parallel() r := registry.New() mustRegTool(t, r, "calc") p := SetContext(r, ActorOwner) if !p.Allow("calc") { t.Fatal("owner should allow an owner-only tool") } if !p.Allow("missing") { t.Fatal("owner should allow a tool that is not registered") } } func TestAllow_GroupAndStrangerMarkers(t *testing.T) { t.Parallel() r := registry.New() mustRegTool(t, r, "groupOnly") mustRegTool(t, r, "strangerOnly") mustRegTool(t, r, "both") mustRegTool(t, r, "ownerOnly") if err := r.SetPolicy("groupOnly", registry.ToolPolicy{AllowInGroup: true}); err != nil { t.Fatalf("SetPolicy groupOnly: %v", err) } if err := r.SetPolicy("strangerOnly", registry.ToolPolicy{AllowInStranger: true}); err != nil { t.Fatalf("SetPolicy strangerOnly: %v", err) } if err := r.SetPolicy("both", registry.ToolPolicy{AllowInGroup: true, AllowInStranger: true}); err != nil { t.Fatalf("SetPolicy both: %v", err) } group := SetContext(r, ActorGroupMember) stranger := SetContext(r, ActorStranger) if !group.Allow("groupOnly") || !group.Allow("both") { t.Fatal("group member should be allowed groupOnly and both") } if group.Allow("strangerOnly") { t.Fatal("group member should be denied strangerOnly") } if group.Allow("ownerOnly") { t.Fatal("group member should be denied ownerOnly") } if !stranger.Allow("strangerOnly") || !stranger.Allow("both") { t.Fatal("stranger should be allowed strangerOnly and both") } if stranger.Allow("groupOnly") { t.Fatal("stranger should be denied groupOnly") } if stranger.Allow("ownerOnly") { t.Fatal("stranger should be denied ownerOnly") } } func TestAllow_FailClosed(t *testing.T) { t.Parallel() // A nil registry denies every tool in a non-owner environment. if p := SetContext(nil, ActorStranger); p.Allow("x") { t.Fatal("nil reg should deny in stranger env") } if p := SetContext(nil, ActorGroupMember); p.Allow("x") { t.Fatal("nil reg should deny in group env") } r := registry.New() mustRegTool(t, r, "t") // An unknown environment denies even a registered tool. if p := SetContext(r, ActorEnv("bogus")); p.Allow("t") { t.Fatal("unknown env should deny") } // An unregistered tool denies. if p := SetContext(r, ActorGroupMember); p.Allow("unknown") { t.Fatal("unknown tool should deny") } // A nil Policy receiver denies. var nilPolicy *Policy if nilPolicy.Allow("t") { t.Fatal("nil Policy receiver should deny") } } func TestDeny_IsInverse(t *testing.T) { t.Parallel() r := registry.New() mustRegTool(t, r, "yes") if err := r.SetAllowInGroup("yes", true); err != nil { t.Fatalf("SetAllowInGroup: %v", err) } mustRegTool(t, r, "no") p := SetContext(r, ActorGroupMember) if p.Allow("yes") != !p.Deny("yes") { t.Fatal("Allow and Deny are not inverses for an allowed tool") } if !p.Deny("no") { t.Fatal("Deny(no) should be true because no is owner-only") } } func TestActorEnv_Valid(t *testing.T) { t.Parallel() for _, env := range []ActorEnv{ActorOwner, ActorGroupMember, ActorStranger} { if !env.Valid() { t.Fatalf("%q should be valid", env) } } if ActorEnv("bogus").Valid() { t.Fatal("bogus env should be invalid") } } func TestPolicy_EnvAndWithLogger(t *testing.T) { t.Parallel() r := registry.New() mustRegTool(t, r, "t") p := SetContext(r, ActorStranger) if p.Env() != ActorStranger { t.Fatalf("Env() = %q, want stranger", p.Env()) } // WithLogger returns a copy and leaves the original unflagged, so the // original's discarding logger still admits no output. cp := p.WithLogger(nil) if cp == nil { t.Fatal("WithLogger(nil) returned nil") } if cp.Env() != ActorStranger { t.Fatalf("copy Env() = %q, want stranger", cp.Env()) } // The copy still denies and reports the same decision. if cp.Allow("t") { t.Fatal("stranger t should be denied without allow_in_stranger") } }