Basic QueryOptions filtering for groups and users

This commit is contained in:
Abin Simon
2022-03-29 15:09:19 +05:30
parent 6d21e29d81
commit cf0b830924
37 changed files with 1493 additions and 917 deletions
+50 -34
View File
@@ -9,7 +9,9 @@ import (
"github.com/RafayLabs/rcloud-base/internal/dao"
"github.com/RafayLabs/rcloud-base/internal/models"
"github.com/RafayLabs/rcloud-base/pkg/query"
authzv1 "github.com/RafayLabs/rcloud-base/proto/types/authz"
commonv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
v3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
userv3 "github.com/RafayLabs/rcloud-base/proto/types/userpb/v3"
"github.com/google/uuid"
@@ -35,7 +37,7 @@ type GroupService interface {
// delete group
Delete(context.Context, *userv3.Group) (*userv3.Group, error)
// list groups
List(context.Context, *userv3.Group) (*userv3.GroupList, error)
List(context.Context, ...query.Option) (*userv3.GroupList, error)
}
// groupService implements GroupService
@@ -250,6 +252,7 @@ func (s *groupService) createGroupAccountRelations(ctx context.Context, db bun.I
return group, nil
}
// TODO: move this to utils, make it accept two strings (names)
func (s *groupService) getPartnerOrganization(ctx context.Context, db bun.IDB, group *userv3.Group) (uuid.UUID, uuid.UUID, error) {
partner := group.GetMetadata().GetPartner()
org := group.GetMetadata().GetOrganization()
@@ -508,7 +511,7 @@ func (s *groupService) Delete(ctx context.Context, group *userv3.Group) (*userv3
return &userv3.Group{}, fmt.Errorf("unable to delete group")
}
func (s *groupService) List(ctx context.Context, group *userv3.Group) (*userv3.GroupList, error) {
func (s *groupService) List(ctx context.Context, opts ...query.Option) (*userv3.GroupList, error) {
var groups []*userv3.Group
groupList := &userv3.GroupList{
ApiVersion: apiVersion,
@@ -517,39 +520,52 @@ func (s *groupService) List(ctx context.Context, group *userv3.Group) (*userv3.G
Count: 0,
},
}
if len(group.Metadata.Organization) > 0 {
orgId, err := dao.GetOrganizationId(ctx, s.db, group.Metadata.Organization)
if err != nil {
return groupList, err
}
partId, err := dao.GetPartnerId(ctx, s.db, group.Metadata.Partner)
if err != nil {
return groupList, err
}
var grps []models.Group
entities, err := dao.List(ctx, s.db, uuid.NullUUID{UUID: partId, Valid: true}, uuid.NullUUID{UUID: orgId, Valid: true}, &grps)
if err != nil {
return groupList, err
}
if grps, ok := entities.(*[]models.Group); ok {
for _, grp := range *grps {
entry := &userv3.Group{Metadata: group.GetMetadata()}
entry, err = s.toV3Group(ctx, s.db, entry, &grp)
if err != nil {
return groupList, err
}
groups = append(groups, entry)
}
//update the list metadata and items response
groupList.Metadata = &v3.ListMetadata{
Count: int64(len(groups)),
}
groupList.Items = groups
}
} else {
return groupList, fmt.Errorf("missing organization id in metadata")
queryOptions := commonv3.QueryOptions{}
for _, opt := range opts {
opt(&queryOptions)
}
orgId, err := dao.GetOrganizationId(ctx, s.db, queryOptions.Organization)
if err != nil {
return groupList, err
}
partId, err := dao.GetPartnerId(ctx, s.db, queryOptions.Partner)
if err != nil {
return groupList, err
}
var grps []models.Group
entities, err := dao.ListFiltered(ctx, s.db,
uuid.NullUUID{UUID: partId, Valid: true}, uuid.NullUUID{UUID: orgId, Valid: true},
&grps,
queryOptions.Q,
queryOptions.OrderBy,
queryOptions.Order,
int(queryOptions.Limit),
int(queryOptions.Offset),
)
if err != nil {
return groupList, err
}
if grps, ok := entities.(*[]models.Group); ok {
for _, grp := range *grps {
entry := &userv3.Group{Metadata: &commonv3.Metadata{
Organization: queryOptions.Organization,
Partner: queryOptions.Partner,
}}
entry, err = s.toV3Group(ctx, s.db, entry, &grp)
if err != nil {
return groupList, err
}
groups = append(groups, entry)
}
//update the list metadata and items response
groupList.Metadata = &v3.ListMetadata{
Count: int64(len(groups)),
}
groupList.Items = groups
}
return groupList, nil
}
+61 -4
View File
@@ -6,6 +6,8 @@ import (
"testing"
"github.com/DATA-DOG/go-sqlmock"
"github.com/RafayLabs/rcloud-base/pkg/query"
commonv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
v3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
userv3 "github.com/RafayLabs/rcloud-base/proto/types/userpb/v3"
"github.com/google/uuid"
@@ -663,10 +665,8 @@ func TestGroupList(t *testing.T) {
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id WHERE .authsrv_projectgroupnamespacerole.group_id = '` + guuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
group := &userv3.Group{
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid},
}
grouplist, err := gs.List(context.Background(), group)
qo := &commonv3.QueryOptions{}
grouplist, err := gs.List(context.Background(), query.WithOptions(qo))
if err != nil {
t.Fatal("could not list groups:", err)
}
@@ -680,3 +680,60 @@ func TestGroupList(t *testing.T) {
t.Errorf("incorrect username in for group, expected johndoe@provider.com ; got '%v'", grouplist.Items[0].GetSpec().GetUsers()[0])
}
}
func TestGroupListFiltered(t *testing.T) {
db, mock := getDB(t)
defer db.Close()
mazc := mockAuthzClient{}
gs := NewGroupService(db, &mazc)
guuid1 := uuid.New().String()
guuid2 := uuid.New().String()
puuid := uuid.New().String()
ouuid := uuid.New().String()
uuuid := uuid.New().String()
ruuid := uuid.New().String()
pruuid := uuid.New().String()
mock.ExpectQuery(`SELECT "organization"."id" FROM "authsrv_organization" AS "organization"`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(ouuid))
mock.ExpectQuery(`SELECT "partner"."id" FROM "authsrv_partner" AS "partner"`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(puuid))
mock.ExpectQuery(`SELECT "group"."id", "group"."name", .*WHERE .name ILIKE '%filter-query%'. AND .partner_id = '` + puuid + `'. AND .organization_id = '` + ouuid + `'. ORDER BY "email" asc LIMIT 50 OFFSET 20`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).
AddRow(guuid1, "group-"+guuid1).AddRow(guuid2, "group-"+guuid2))
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" JOIN authsrv_groupaccount ON identities.id=authsrv_groupaccount.account_id WHERE .authsrv_groupaccount.group_id = '` + guuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id WHERE .authsrv_grouprole.group_id = '` + guuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id WHERE .authsrv_projectgrouprole.group_id = '` + guuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id WHERE .authsrv_projectgroupnamespacerole.group_id = '` + guuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
mock.ExpectQuery(`SELECT "identities"."id".* FROM "identities" JOIN authsrv_groupaccount ON identities.id=authsrv_groupaccount.account_id WHERE .authsrv_groupaccount.group_id = '` + guuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).AddRow(uuuid, []byte(`{"email":"johndoe@provider.com"}`)))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_grouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_grouprole.role_id WHERE .authsrv_grouprole.group_id = '` + guuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectgrouprole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgrouprole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgrouprole.project_id WHERE .authsrv_projectgrouprole.group_id = '` + guuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectgroupnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectgroupnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectgroupnamespacerole.project_id WHERE .authsrv_projectgroupnamespacerole.group_id = '` + guuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
qo := &commonv3.QueryOptions{Q: "filter-query", Limit: 50, Offset: 20, OrderBy: "email", Order: "asc"}
grouplist, err := gs.List(context.Background(), query.WithOptions(qo))
if err != nil {
t.Fatal("could not list groups:", err)
}
if grouplist.Metadata.Count != 2 {
t.Errorf("incorrect number of groups returned, expected 2; got %v", grouplist.Metadata.Count)
}
if grouplist.Items[0].Metadata.Name != "group-"+guuid1 {
t.Errorf("incorrect group ids returned when listing")
}
if grouplist.Items[0].GetSpec().GetUsers()[0] != "johndoe@provider.com" {
t.Errorf("incorrect username in for group, expected johndoe@provider.com ; got '%v'", grouplist.Items[0].GetSpec().GetUsers()[0])
}
}
+63 -13
View File
@@ -15,8 +15,10 @@ import (
"github.com/RafayLabs/rcloud-base/internal/models"
providers "github.com/RafayLabs/rcloud-base/internal/provider/kratos"
"github.com/RafayLabs/rcloud-base/pkg/common"
"github.com/RafayLabs/rcloud-base/pkg/query"
userrpcv3 "github.com/RafayLabs/rcloud-base/proto/rpc/user"
authzv1 "github.com/RafayLabs/rcloud-base/proto/types/authz"
commonv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
v3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
userv3 "github.com/RafayLabs/rcloud-base/proto/types/userpb/v3"
)
@@ -39,7 +41,7 @@ type UserService interface {
// delete user
Delete(context.Context, *userv3.User) (*userrpcv3.DeleteUserResponse, error)
// list users
List(context.Context, *userv3.User) (*userv3.UserList, error)
List(context.Context, ...query.Option) (*userv3.UserList, error)
// retrieve the cli config for the logged in user
RetrieveCliConfig(ctx context.Context, req *userrpcv3.ApiKeyRequest) (*common.CliConfigDownloadData, error)
}
@@ -488,7 +490,7 @@ func (s *userService) Delete(ctx context.Context, user *userv3.User) (*userrpcv3
}
func (s *userService) List(ctx context.Context, _ *userv3.User) (*userv3.UserList, error) {
func (s *userService) List(ctx context.Context, opts ...query.Option) (*userv3.UserList, error) {
var users []*userv3.User
userList := &userv3.UserList{
ApiVersion: apiVersion,
@@ -497,12 +499,60 @@ func (s *userService) List(ctx context.Context, _ *userv3.User) (*userv3.UserLis
Count: 0,
},
}
var accs []models.KratosIdentities
entities, err := dao.ListAll(ctx, s.db, &accs)
if err != nil {
return userList, err
queryOptions := commonv3.QueryOptions{}
for _, opt := range opts {
opt(&queryOptions)
}
if usrs, ok := entities.(*[]models.KratosIdentities); ok {
// TODO: group relation stuff
// TODO: This is kinda expensive to compute
upr, err := getUserProjectRoles(ctx, s.db)
if err != nil {
return &userv3.UserList{}, err
}
fmt.Println("upr:", upr)
projects := []string{}
fmt.Println("queryOptions.Project:", queryOptions.Project)
if queryOptions.Project != "" {
projects = strings.Split(queryOptions.Project, ",")
}
// TODO: make this a single big query
fupr, err := filterUserProjectRoles(upr,
projects,
"role-name", // TODO: add role to QueryOptions
// queryOptions.Role,
)
if err != nil {
return &userv3.UserList{}, err
}
fmt.Println("fupr:", fupr)
uids := []uuid.UUID{}
for k := range fupr {
uids = append(uids, k)
}
// TODO: add gorup to search
if queryOptions.Group {
// partnerId, organizationId, err := s.getPartnerOrganization(ctx, s.db, group)
// if err != nil {
// return nil, fmt.Errorf("unable to get partner and org id")
// }
ga := []models.GroupAccount{}
g, err := dao.Get(ctx, )
}
if len(fupr) != 0 {
var accs []models.KratosIdentities
usrs, err := dao.ListFilteredUsers(ctx, s.db, &accs,
uids, queryOptions.Q,
queryOptions.OrderBy, queryOptions.Order,
int(queryOptions.Limit), int(queryOptions.Offset))
if err != nil {
return userList, err
}
for _, usr := range *usrs {
user := &userv3.User{}
user, err := s.identitiesModelToUser(ctx, s.db, user, &usr)
@@ -511,14 +561,14 @@ func (s *userService) List(ctx context.Context, _ *userv3.User) (*userv3.UserLis
}
users = append(users, user)
}
// update the list metadata and items response
userList.Metadata = &v3.ListMetadata{
Count: int64(len(users)),
}
userList.Items = users
}
// update the list metadata and items response
userList.Metadata = &v3.ListMetadata{
Count: int64(len(users)),
}
userList.Items = users
return userList, nil
}
+71 -4
View File
@@ -7,6 +7,8 @@ import (
"github.com/DATA-DOG/go-sqlmock"
"github.com/RafayLabs/rcloud-base/pkg/common"
"github.com/RafayLabs/rcloud-base/pkg/query"
commonv3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
v3 "github.com/RafayLabs/rcloud-base/proto/types/commonpb/v3"
userv3 "github.com/RafayLabs/rcloud-base/proto/types/userpb/v3"
"github.com/google/uuid"
@@ -362,10 +364,8 @@ func TestUserList(t *testing.T) {
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
user := &userv3.User{
Metadata: &v3.Metadata{Partner: "partner-" + puuid, Organization: "org-" + ouuid},
}
userlist, err := us.List(context.Background(), user)
qo := &commonv3.QueryOptions{}
userlist, err := us.List(context.Background(), query.WithOptions(qo))
if err != nil {
t.Fatal("could not list users:", err)
}
@@ -388,6 +388,73 @@ func TestUserList(t *testing.T) {
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
}
func TestUserFiletered(t *testing.T) {
db, mock := getDB(t)
defer db.Close()
ap := &mockAuthProvider{}
mazc := mockAuthzClient{}
us := NewUserService(ap, db, &mazc, nil, common.CliConfigDownloadData{})
uuuid1 := uuid.New().String()
uuuid2 := uuid.New().String()
puuid := uuid.New().String()
ouuid := uuid.New().String()
guuid := uuid.New().String()
ruuid := uuid.New().String()
pruuid := uuid.New().String()
mock.ExpectQuery(`SELECT "identities"."id", .*WHERE .traits ->> 'email' ILIKE '%filter-query%'. OR .traits ->> 'first_name' ILIKE '%filter-query%'. OR .traits ->> 'last_name' ILIKE '%filter-query%'. ORDER BY "traits ->> 'email' asc" LIMIT 50 OFFSET 20`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"id", "traits"}).
AddRow(uuuid1, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)).
AddRow(uuuid2, []byte(`{"email":"johndoe@provider.com", "first_name": "John", "last_name": "Doe", "organization_id": "`+ouuid+`", "partner_id": "`+puuid+`", "description": "My awesome user"}`)))
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
AddRow("group-" + guuid).AddRow("group2-" + guuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid1 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
mock.ExpectQuery(`SELECT "group"."id".* FROM "authsrv_group" AS "group" JOIN authsrv_groupaccount ON authsrv_groupaccount.group_id="group".id WHERE .authsrv_groupaccount.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"name"}).
AddRow("group-" + guuid).AddRow("group2-" + guuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role FROM "authsrv_accountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_accountresourcerole.role_id WHERE .authsrv_accountresourcerole.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role"}).AddRow("role-" + ruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project FROM "authsrv_projectaccountresourcerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountresourcerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountresourcerole.project_id WHERE .authsrv_projectaccountresourcerole.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project"}).AddRow("role-"+ruuid, "project-"+pruuid))
mock.ExpectQuery(`SELECT authsrv_resourcerole.name as role, authsrv_project.name as project, namespace_id as namespace FROM "authsrv_projectaccountnamespacerole" JOIN authsrv_resourcerole ON authsrv_resourcerole.id=authsrv_projectaccountnamespacerole.role_id JOIN authsrv_project ON authsrv_project.id=authsrv_projectaccountnamespacerole.project_id WHERE .authsrv_projectaccountnamespacerole.account_id = '` + uuuid2 + `'`).
WithArgs().WillReturnRows(sqlmock.NewRows([]string{"role", "project", "namespace"}).AddRow("role-"+ruuid, "project-"+pruuid, 9))
qo := &commonv3.QueryOptions{Q: "filter-query", Limit: 50, Offset: 20, OrderBy: "email", Order: "asc"}
userlist, err := us.List(context.Background(), query.WithOptions(qo))
if err != nil {
t.Fatal("could not list users:", err)
}
if userlist.Metadata.Count != 2 {
t.Errorf("incorrect number of users returned, expected 2; got %v", userlist.Metadata.Count)
}
if userlist.Items[0].Metadata.Name != "johndoe@provider.com"{
t.Errorf("incorrect user names returned when listing; expected '%v' and '%v'; got '%v' and '%v'", "johndoe@provider.com", "johndoe@provider.com", userlist.Items[0].Metadata.Name, userlist.Items[1].Metadata.Name)
}
if len(userlist.Items[0].GetSpec().GetGroups()) != 2 {
t.Errorf("invalid number of groups returned for user, expected 2; got '%v'", len(userlist.Items[0].GetSpec().GetGroups()))
}
if len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()) != 3 {
t.Errorf("invalid number of roles returned for user, expected 3; got '%v'", len(userlist.Items[0].GetSpec().GetProjectNamespaceRoles()))
}
if userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].GetNamespace() != 9 {
t.Errorf("invalid namespace in role returned for user, expected 9; got '%v'", userlist.Items[0].GetSpec().GetProjectNamespaceRoles()[2].Namespace)
}
performBasicAuthProviderChecks(t, *ap, 0, 0, 0, 0)
}
func TestUserDelete(t *testing.T) {
db, mock := getDB(t)
+76
View File
@@ -1,5 +1,13 @@
package service
import (
"context"
"github.com/RafayLabs/rcloud-base/internal/dao"
"github.com/google/uuid"
"github.com/uptrace/bun"
)
func unique(items []string) []string {
keys := make(map[string]bool)
list := []string{}
@@ -20,3 +28,71 @@ func contains(s []string, str string) bool {
}
return false
}
func remove(l []string, item string) []string {
for i, other := range l {
if other == item {
return append(l[:i], l[i+1:]...)
}
}
return l
}
type projectRole struct {
Project *string
Role string
}
type userProjectRoles map[uuid.UUID][]projectRole
func getUserProjectRoles(ctx context.Context, db bun.IDB) (userProjectRoles, error) {
roles, err := dao.ListUserRoles(ctx, db)
if err != nil {
return userProjectRoles{}, err
}
upr := userProjectRoles{}
for _, role := range roles {
upr[role.AccountId] = append(upr[role.AccountId], projectRole{Project: role.Project, Role: role.Role})
}
return upr, nil
}
func projectAvailable(r []projectRole, projects []string) bool {
// This is an OR internally
// ALL is when the permissions is not project bound
all := false
if contains(projects, "ALL") {
all = true
projects = remove(projects, "ALL")
}
for _, pr := range r {
if pr.Project != nil {
if contains(projects, *pr.Project) {
return true
}
} else if all {
return true
}
}
return false
}
func roleAvailable(r []projectRole, role string) bool {
for _, pr := range r {
if pr.Role == role {
return true
}
}
return false
}
func filterUserProjectRoles(upr userProjectRoles, projects []string, role string) (userProjectRoles, error) {
fupr := userProjectRoles{}
for u, r := range upr {
if (len(projects) == 0 || projectAvailable(r, projects)) && (role == "" || roleAvailable(r, role)) {
fupr[u] = r
}
}
return fupr, nil
}