mirror of
https://github.com/paralus/paralus.git
synced 2026-08-24 15:47:19 +00:00
Basic QueryOptions filtering for groups and users
This commit is contained in:
+50
-34
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user