Files

160 lines
4.6 KiB
Go

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")
}
}