Files
ResolveSpec/pkg/security/writesecurity_test.go
T

101 lines
3.2 KiB
Go

package security
import (
"context"
"reflect"
"testing"
)
type wsCtx struct {
data interface{}
model interface{}
user bool
}
func (c *wsCtx) GetContext() context.Context {
if c.user {
return context.WithValue(context.Background(), UserIDKey, 7)
}
return context.Background()
}
func (c *wsCtx) GetUserID() (int, bool) { return 7, c.user }
func (c *wsCtx) GetUserRef() (any, bool) { return 7, c.user }
func (c *wsCtx) GetSchema() string { return "public" }
func (c *wsCtx) GetEntity() string { return "items" }
func (c *wsCtx) GetModel() interface{} { return c.model }
func (c *wsCtx) GetQuery() interface{} { return nil }
func (c *wsCtx) SetQuery(interface{}) {}
func (c *wsCtx) GetResult() interface{} { return nil }
func (c *wsCtx) SetResult(interface{}) {}
func (c *wsCtx) GetData() interface{} { return c.data }
func (c *wsCtx) SetData(d interface{}) { c.data = d }
type wsModel struct {
ID int `json:"id" bun:"id,pk"`
Name string `json:"name" bun:"name"`
Email string `json:"email" gorm:"column:email_addr"`
Other string `json:"other" bun:"other"`
}
func wsList(rules ...ColumnSecurity) *SecurityList {
l := &SecurityList{ColumnSecurity: map[string][]ColumnSecurity{"public.items@7": rules}}
if rules == nil {
l.ColumnSecurity["public.items@7"] = []ColumnSecurity{}
}
return l
}
func TestApplyWriteColumnSecurityStripsHiddenAndMasked(t *testing.T) {
list := wsList(
ColumnSecurity{Path: []string{"Name"}, Accesstype: "hide"},
ColumnSecurity{Path: []string{"email_addr"}, Accesstype: "mask"},
ColumnSecurity{Path: []string{"other"}, Accesstype: "allow"},
ColumnSecurity{Path: []string{"id", "sub"}, Accesstype: "hide"},
)
tests := map[string]struct{ in, want interface{} }{
"map": {
map[string]interface{}{"id": 1, "name": "a", "email": "e", "other": "o"},
map[string]interface{}{"id": 1, "other": "o"},
},
"slice": {
[]interface{}{map[string]interface{}{"NAME": "a", "id": 1}, map[string]interface{}{"email_addr": "e"}},
[]interface{}{map[string]interface{}{"id": 1}, map[string]interface{}{}},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
c := &wsCtx{data: tc.in, model: &wsModel{}, user: true}
if err := ApplyWriteColumnSecurity(c, list); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(c.data, tc.want) {
t.Fatalf("got %v want %v", c.data, tc.want)
}
})
}
}
func TestApplyWriteColumnSecurityNoRulesKeepsPayload(t *testing.T) {
c := &wsCtx{data: map[string]interface{}{"name": "a"}, model: &wsModel{}, user: true}
if err := ApplyWriteColumnSecurity(c, wsList()); err != nil {
t.Fatal(err)
}
if _, ok := c.data.(map[string]interface{})["name"]; !ok {
t.Fatal("payload changed without rules")
}
}
func TestApplyWriteColumnSecurityFailsClosedWhenRulesNotLoaded(t *testing.T) {
c := &wsCtx{data: map[string]interface{}{"name": "a"}, model: &wsModel{}, user: true}
if err := ApplyWriteColumnSecurity(c, &SecurityList{}); err == nil {
t.Fatal("expected an error when rules are not loaded")
}
}
func TestApplyWriteColumnSecuritySkipsWithoutUser(t *testing.T) {
c := &wsCtx{data: map[string]interface{}{"name": "a"}, model: &wsModel{}}
if err := ApplyWriteColumnSecurity(c, &SecurityList{}); err != nil {
t.Fatal(err)
}
}