- classes: every admin action for its changed-row count and idempotency, the ban across several throttle rows, the cleanup of a permanent delete - classes: the privileged list and IsPrivilegedMember (D-30), also through a handle that carries conditions - classes: the five-minute boundary of last_seen - models: PermissionSet round trip, the slug table shared with the SPA, Fillable and Rules, fields that never marshal, the group filter value - TestAdminRegistration: permissions, navigation, embedded files and phrase keys in en and pl; the admin secret is required
91 lines
3.5 KiB
Go
91 lines
3.5 KiB
Go
package models
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
// TestPermissionSetRoundTrip: what Value writes, Scan and ParsePermissionSet
|
|
// read back unchanged; Text is the same text for a plain string column.
|
|
func TestPermissionSetRoundTrip(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
set PermissionSet
|
|
text string // "" stands for NULL
|
|
back PermissionSet
|
|
}{
|
|
{"allow and deny", PermissionSet{"blog.post": 1, "blog.edit": -1}, `{"blog.edit":-1,"blog.post":1}`, PermissionSet{"blog.post": 1, "blog.edit": -1}},
|
|
{"a zero is not stored", PermissionSet{"blog.post": 1, "blog.zero": 0}, `{"blog.post":1}`, PermissionSet{"blog.post": 1}},
|
|
{"a wildcard code", PermissionSet{"blog.*": 1}, `{"blog.*":1}`, PermissionSet{"blog.*": 1}},
|
|
{"an empty set", PermissionSet{}, "", PermissionSet{}},
|
|
{"a nil set", nil, "", PermissionSet{}},
|
|
{"only zeros", PermissionSet{"blog.zero": 0}, "", PermissionSet{}},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
value, err := tc.set.Value()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
text := tc.set.Text()
|
|
if tc.text == "" {
|
|
if value != nil || text != nil {
|
|
t.Fatalf("Value = %#v, Text = %v, want NULL", value, text)
|
|
}
|
|
} else if value != tc.text || text == nil || *text != tc.text {
|
|
t.Fatalf("Value = %#v, Text = %v, want %s", value, text, tc.text)
|
|
}
|
|
var scanned PermissionSet
|
|
if err := scanned.Scan(value); err != nil || !reflect.DeepEqual(scanned, tc.back) {
|
|
t.Fatalf("Scan(Value) = %v %v, want %v", scanned, err, tc.back)
|
|
}
|
|
parsed, err := ParsePermissionSet([]byte(tc.text))
|
|
if err != nil || !reflect.DeepEqual(parsed, tc.back) {
|
|
t.Fatalf("ParsePermissionSet(%q) = %v %v, want %v", tc.text, parsed, err, tc.back)
|
|
}
|
|
})
|
|
}
|
|
if got := (PermissionSet{}).GormDataType(); got != "text" {
|
|
t.Fatalf("GormDataType = %q", got)
|
|
}
|
|
}
|
|
|
|
// TestParsePermissionSet: the tolerant read of what PHP may have stored, and
|
|
// the error for content that is not a JSON object.
|
|
func TestParsePermissionSet(t *testing.T) {
|
|
for raw, want := range map[string]PermissionSet{
|
|
"": {},
|
|
" ": {},
|
|
"[]": {},
|
|
"null": {},
|
|
" {} ": {},
|
|
`{"a":1,"b":"1","c":" -1 "}`: {"a": 1, "b": 1, "c": -1},
|
|
// Values that are not integers are skipped, never read as granted.
|
|
`{"a":true,"b":"yes","c":1.5,"d":null,"e":[1],"f":{"x":1},"g":1}`: {"g": 1},
|
|
`{"big":99999999999999999999}`: {},
|
|
} {
|
|
got, err := ParsePermissionSet([]byte(raw))
|
|
if err != nil || got == nil || !reflect.DeepEqual(got, want) {
|
|
t.Errorf("ParsePermissionSet(%q) = %v %v, want %v", raw, got, err, want)
|
|
}
|
|
}
|
|
for _, raw := range []string{`{"a":1`, `["a"]`, `1`, `"a"`, `true`, `{"a":1}{"b":1}`, `{"a":1} x`} {
|
|
if got, err := ParsePermissionSet([]byte(raw)); err == nil {
|
|
t.Errorf("ParsePermissionSet(%q) = %v, want an error", raw, got)
|
|
}
|
|
}
|
|
// Scan keeps the previous value on an error and takes text or bytes.
|
|
set := PermissionSet{"kept": 1}
|
|
if err := set.Scan(`["a"]`); err == nil || !reflect.DeepEqual(set, PermissionSet{"kept": 1}) {
|
|
t.Fatalf("a failed Scan changed the set: %v %v", set, err)
|
|
}
|
|
if err := set.Scan([]byte(`{"a":-1}`)); err != nil || !reflect.DeepEqual(set, PermissionSet{"a": -1}) {
|
|
t.Fatalf("Scan(bytes) = %v %v", set, err)
|
|
}
|
|
if err := set.Scan(nil); err != nil || set == nil || len(set) != 0 {
|
|
t.Fatalf("Scan(nil) = %#v %v", set, err)
|
|
}
|
|
if err := set.Scan(3.5); err == nil {
|
|
t.Fatal("Scan accepted a float")
|
|
}
|
|
}
|