mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-10-01 19:20:31 +00:00
101 lines
3.2 KiB
Go
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)
|
|
}
|
|
}
|