package authz import ( "testing" "github.com/stretchr/testify/assert" "github.com/zitadel/zitadel/internal/zerrors" ) type TestRequest struct { Test string } func Test_CheckUserPermissions(t *testing.T) { type args struct { req *TestRequest perms []string authOpt Option } tests := []struct { name string args args wantErr bool }{ { name: "no permissions", args: args{ req: &TestRequest{}, perms: []string{}, }, wantErr: true, }, { name: "has permission and no context requested", args: args{ req: &TestRequest{}, perms: []string{"project.read"}, authOpt: Option{CheckParam: ""}, }, wantErr: false, }, { name: "context requested and has global permission", args: args{ req: &TestRequest{Test: "Test"}, perms: []string{"project.read", "project.read:1"}, authOpt: Option{CheckParam: "Test"}, }, wantErr: false, }, { name: "context requested and has specific permission", args: args{ req: &TestRequest{Test: "Test"}, perms: []string{"project.read:Test"}, authOpt: Option{CheckParam: "Test"}, }, wantErr: false, }, { name: "context requested and has no permission", args: args{ req: &TestRequest{Test: "Hodor"}, perms: []string{"project.read:Test"}, authOpt: Option{CheckParam: "Test"}, }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := checkUserPermissions(tt.args.req, tt.args.perms, tt.args.authOpt) if tt.wantErr && err == nil { t.Errorf("got wrong result, should get err: actual: %v ", err) } if !tt.wantErr && err != nil { t.Errorf("shouldn't get err: %v ", err) } if tt.wantErr && !zerrors.IsPermissionDenied(err) { t.Errorf("got wrong err: %v ", err) } }) } } func Test_SplitPermission(t *testing.T) { type args struct { perm string } tests := []struct { name string args args permName string permCtxID string }{ { name: "permission with context id", args: args{ perm: "project.read:ctxID", }, permName: "project.read", permCtxID: "ctxID", }, { name: "permission without context id", args: args{ perm: "project.read", }, permName: "project.read", permCtxID: "", }, { name: "permission to many parts", args: args{ perm: "project.read:1:0", }, permName: "project.read", permCtxID: "1", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { name, id := SplitPermission(tt.args.perm) if name != tt.permName { t.Errorf("got wrong result on name, expecting: %v, actual: %v ", tt.permName, name) } if id != tt.permCtxID { t.Errorf("got wrong result on id, expecting: %v, actual: %v ", tt.permCtxID, id) } }) } } func Test_HasContextPermission(t *testing.T) { type args struct { req *TestRequest fieldname string perms []string } tests := []struct { name string args args result bool }{ { name: "existing context permission", args: args{ req: &TestRequest{Test: "right"}, fieldname: "Test", perms: []string{"test:wrong", "test:right"}, }, result: true, }, { name: "not existing context permission", args: args{ req: &TestRequest{Test: "test"}, fieldname: "Test", perms: []string{"test:wrong", "test:wrong2"}, }, result: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := hasContextPermission(tt.args.req, tt.args.fieldname, tt.args.perms) if result != tt.result { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) } }) } } func Test_GetFieldFromReq(t *testing.T) { type args struct { req *TestRequest fieldname string } tests := []struct { name string args args result string }{ { name: "existing field", args: args{ req: &TestRequest{Test: "TestValue"}, fieldname: "Test", }, result: "TestValue", }, { name: "not existing field", args: args{ req: &TestRequest{Test: "TestValue"}, fieldname: "Test2", }, result: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := getFieldFromReq(tt.args.req, tt.args.fieldname) if result != tt.result { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) } }) } } func Test_HasGlobalPermission(t *testing.T) { type args struct { perms []string } tests := []struct { name string args args result bool }{ { name: "global perm existing", args: args{ perms: []string{"perm:1", "perm:2", "perm"}, }, result: true, }, { name: "global perm not existing", args: args{ perms: []string{"perm:1", "perm:2", "perm:3"}, }, result: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := HasGlobalPermission(tt.args.perms) if result != tt.result { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) } }) } } func Test_GetPermissionCtxIDs(t *testing.T) { type args struct { perms []string } tests := []struct { name string args args result []string }{ { name: "no specific permission", args: args{ perms: []string{"perm"}, }, result: []string{}, }, { name: "ctx id", args: args{ perms: []string{"perm:1", "perm", "perm:3"}, }, result: []string{"1", "3"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := GetAllPermissionCtxIDs(tt.args.perms) if !equalStringArray(result, tt.result) { t.Errorf("got wrong result, expecting: %v, actual: %v ", tt.result, result) } }) } } func Test_systemMembershipsToUserPermissions(t *testing.T) { roleMap := []RoleMapping{ { Role: "FOO_BAR", Permissions: []string{"foo.bar.read", "foo.bar.write"}, }, { Role: "BAR_FOO", Permissions: []string{"bar.foo.read", "bar.foo.write", "foo.bar.read"}, }, } type args struct { memberships Memberships roleMap []RoleMapping } tests := []struct { name string args args want []SystemUserPermissions }{ { name: "nil memberships", args: args{ memberships: nil, roleMap: roleMap, }, want: nil, }, { name: "empty memberships", args: args{ memberships: Memberships{}, roleMap: roleMap, }, want: []SystemUserPermissions{}, }, { name: "single membership", args: args{ memberships: Memberships{ { MemberType: MemberTypeSystem, AggregateID: "1", ObjectID: "2", Roles: []string{"FOO_BAR"}, }, }, roleMap: roleMap, }, want: []SystemUserPermissions{ { MemberType: MemberTypeSystem, AggregateID: "1", ObjectID: "2", Permissions: []string{"foo.bar.read", "foo.bar.write"}, }, }, }, { name: "multiple memberships", args: args{ memberships: Memberships{ { MemberType: MemberTypeSystem, AggregateID: "1", ObjectID: "2", Roles: []string{"FOO_BAR"}, }, { MemberType: MemberTypeIAM, AggregateID: "1", ObjectID: "2", Roles: []string{"BAR_FOO"}, }, }, roleMap: roleMap, }, want: []SystemUserPermissions{ { MemberType: MemberTypeSystem, AggregateID: "1", ObjectID: "2", Permissions: []string{"foo.bar.read", "foo.bar.write"}, }, { MemberType: MemberTypeIAM, AggregateID: "1", ObjectID: "2", Permissions: []string{"bar.foo.read", "bar.foo.write", "foo.bar.read"}, }, }, }, { name: "multiple roles", args: args{ memberships: Memberships{ { MemberType: MemberTypeSystem, AggregateID: "1", ObjectID: "2", Roles: []string{"FOO_BAR", "BAR_FOO"}, }, }, roleMap: roleMap, }, want: []SystemUserPermissions{ { MemberType: MemberTypeSystem, AggregateID: "1", ObjectID: "2", Permissions: []string{"bar.foo.read", "bar.foo.write", "foo.bar.read", "foo.bar.write"}, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := systemMembershipsToUserPermissions(tt.args.memberships, tt.args.roleMap) assert.Equal(t, tt.want, got) }) } }