2020-06-15 15:22:41 -07:00
// Copyright (c) HashiCorp, Inc.
2023-02-02 17:15:17 -08:00
// SPDX-License-Identifier: BUSL-1.1
2020-06-15 15:22:41 -07:00
package groups_test
import (
"context"
2020-09-23 08:10:27 -07:00
"errors"
2020-06-15 15:22:41 -07:00
"fmt"
2023-12-21 12:54:27 -08:00
"slices"
2020-06-15 15:22:41 -07:00
"strings"
"testing"
2020-07-22 15:10:21 -07:00
"github.com/google/go-cmp/cmp"
2023-10-31 13:44:17 +00:00
"github.com/google/go-cmp/cmp/cmpopts"
2022-10-28 15:52:06 -04:00
"github.com/hashicorp/boundary/globals"
2023-12-21 12:54:27 -08:00
"github.com/hashicorp/boundary/internal/auth/password"
"github.com/hashicorp/boundary/internal/authtoken"
2022-05-09 12:45:10 -07:00
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/groups"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/db"
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
2023-12-21 12:54:27 -08:00
authpb "github.com/hashicorp/boundary/internal/gen/controller/auth"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/iam"
2023-12-21 12:54:27 -08:00
"github.com/hashicorp/boundary/internal/kms"
"github.com/hashicorp/boundary/internal/requests"
"github.com/hashicorp/boundary/internal/server"
2020-08-10 17:15:02 -04:00
"github.com/hashicorp/boundary/internal/types/scope"
2021-08-26 10:44:41 -04:00
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/groups"
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
2020-06-15 15:22:41 -07:00
"google.golang.org/genproto/protobuf/field_mask"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
2020-07-22 15:10:21 -07:00
"google.golang.org/protobuf/testing/protocmp"
2021-04-23 09:13:37 -05:00
"google.golang.org/protobuf/types/known/timestamppb"
2020-06-15 15:22:41 -07:00
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
2021-04-23 09:13:37 -05:00
var testAuthorizedActions = [] string { "no-op" , "read" , "update" , "delete" , "add-members" , "set-members" , "remove-members" }
2020-06-29 11:12:40 -07:00
// Creates an org scoped group and a project scoped group.
func createDefaultGroupsAndRepo ( t * testing . T ) ( * iam . Group , * iam . Group , func () ( * iam . Repository , error )) {
2020-06-15 15:22:41 -07:00
t . Helper ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-06-15 15:22:41 -07:00
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-06-15 15:22:41 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-06-15 15:22:41 -07:00
}
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2020-06-29 11:12:40 -07:00
og := iam . TestGroup ( t , conn , o . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
pg := iam . TestGroup ( t , conn , p . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
return og , pg , repoFn
2020-06-15 15:22:41 -07:00
}
2020-07-22 15:10:21 -07:00
func equalMembers ( g * pb . Group , members [] string ) bool {
if len ( g . Members ) != len ( members ) {
return false
}
for _ , m := range members {
var foundInMembers bool
var foundInPrincipalIds bool
for _ , v := range g . Members {
if v . Id == m {
foundInMembers = true
}
}
for _ , v := range g . MemberIds {
if v == m {
foundInPrincipalIds = true
}
}
if ! foundInMembers || ! foundInPrincipalIds {
return false
}
}
return true
}
2020-06-15 15:22:41 -07:00
func TestGet ( t * testing . T ) {
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-22 15:10:21 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-22 15:10:21 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-22 15:10:21 -07:00
}
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
u := iam . TestUser ( t , iamRepo , o . GetPublicId ())
2020-07-22 15:10:21 -07:00
og := iam . TestGroup ( t , conn , o . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
_ = iam . TestGroupMember ( t , conn , og . GetPublicId (), u . GetPublicId ())
pg := iam . TestGroup ( t , conn , p . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
_ = iam . TestGroupMember ( t , conn , pg . GetPublicId (), u . GetPublicId ())
2020-06-15 15:22:41 -07:00
toMerge := & pbs . GetGroupRequest {
2020-07-22 00:14:28 -04:00
Id : og . GetPublicId (),
2020-06-15 15:22:41 -07:00
}
2020-06-29 11:12:40 -07:00
wantOrgGroup := & pb . Group {
Id : og . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : og . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : og . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2020-06-29 11:12:40 -07:00
Name : & wrapperspb . StringValue { Value : og . GetName ()},
Description : & wrapperspb . StringValue { Value : og . GetDescription ()},
CreatedTime : og . CreateTime . GetTimestamp (),
UpdatedTime : og . UpdateTime . GetTimestamp (),
2020-07-22 15:10:21 -07:00
Version : 1 ,
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
}
wantProjGroup := & pb . Group {
Id : pg . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : pg . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pg . GetScopeId (), Type : scope . Project . String (), ParentScopeId : o . GetPublicId ()},
2020-06-29 11:12:40 -07:00
Name : & wrapperspb . StringValue { Value : pg . GetName ()},
Description : & wrapperspb . StringValue { Value : pg . GetDescription ()},
CreatedTime : pg . CreateTime . GetTimestamp (),
UpdatedTime : pg . UpdateTime . GetTimestamp (),
2020-07-22 15:10:21 -07:00
Version : 1 ,
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-15 15:22:41 -07:00
}
cases := [] struct {
name string
2020-07-22 00:14:28 -04:00
scopeId string
2020-06-15 15:22:41 -07:00
req * pbs . GetGroupRequest
res * pbs . GetGroupResponse
2020-09-23 08:10:27 -07:00
err error
2020-06-15 15:22:41 -07:00
}{
{
name : "Get an Existing Group" ,
2020-07-22 00:14:28 -04:00
scopeId : og . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . GetGroupRequest { Id : og . GetPublicId ()},
res : & pbs . GetGroupResponse { Item : wantOrgGroup },
2020-06-15 15:22:41 -07:00
},
{
2024-02-16 08:30:16 -05:00
name : "Get a non existent Group" ,
2023-03-10 15:06:39 -05:00
req : & pbs . GetGroupRequest { Id : globals . GroupPrefix + "_DoesntExis" },
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-15 15:22:41 -07:00
},
{
2020-09-23 08:10:27 -07:00
name : "Wrong id prefix" ,
req : & pbs . GetGroupRequest { Id : "j_1234567890" },
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
2020-09-23 08:10:27 -07:00
name : "space in id" ,
2023-03-10 15:06:39 -05:00
req : & pbs . GetGroupRequest { Id : globals . GroupPrefix + "_1 23456789" },
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
2020-06-29 11:12:40 -07:00
{
name : "Project Scoped Get an Existing Group" ,
2020-07-22 00:14:28 -04:00
scopeId : pg . GetScopeId (),
req : & pbs . GetGroupRequest { Id : pg . GetPublicId ()},
2020-06-29 11:12:40 -07:00
res : & pbs . GetGroupResponse { Item : wantProjGroup },
},
{
2024-02-16 08:30:16 -05:00
name : "Project Scoped Get a non existent Group" ,
2020-07-22 00:14:28 -04:00
scopeId : pg . GetScopeId (),
2023-03-10 15:06:39 -05:00
req : & pbs . GetGroupRequest { Id : globals . GroupPrefix + "_DoesntExis" },
2020-06-29 11:12:40 -07:00
res : nil ,
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-29 11:12:40 -07:00
},
{
name : "Project Scoped Wrong id prefix" ,
2020-07-22 00:14:28 -04:00
scopeId : pg . GetScopeId (),
req : & pbs . GetGroupRequest { Id : "j_1234567890" },
2020-06-29 11:12:40 -07:00
res : nil ,
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-29 11:12:40 -07:00
},
{
name : "Project Scoped space in id" ,
2020-07-22 00:14:28 -04:00
scopeId : pg . GetScopeId (),
2023-03-10 15:06:39 -05:00
req : & pbs . GetGroupRequest { Id : globals . GroupPrefix + "_1 23456789" },
2020-06-29 11:12:40 -07:00
res : nil ,
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-29 11:12:40 -07:00
},
2020-06-15 15:22:41 -07:00
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-07-22 15:10:21 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-15 15:22:41 -07:00
req := proto . Clone ( toMerge ).( * pbs . GetGroupRequest )
proto . Merge ( req , tc . req )
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( ctx , repoFn , 1000 )
2020-06-15 15:22:41 -07:00
require . NoError ( err , "Couldn't create new group service." )
2021-03-25 03:15:43 -04:00
got , gErr := s . GetGroup ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "GetGroup(%+v) got error %v, wanted %v" , req , gErr , tc . err )
}
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "GetGroup(%q) got response\n%q, wanted\n%q" , req , got , tc . res )
2020-06-15 15:22:41 -07:00
})
}
}
2020-06-22 10:46:45 -07:00
func TestList ( t * testing . T ) {
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-06 10:15:01 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
2020-06-22 10:46:45 -07:00
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-06-22 10:46:45 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-06-22 10:46:45 -07:00
}
2020-08-19 16:47:18 -04:00
oNoGroups , pWithGroups := iam . TestScopes ( t , iamRepo )
oWithGroups , pNoGroups := iam . TestScopes ( t , iamRepo )
2023-12-21 12:54:27 -08:00
var wantGlobalGroups [] * pb . Group
2020-06-29 11:12:40 -07:00
var wantOrgGroups [] * pb . Group
var wantProjGroups [] * pb . Group
2021-01-25 19:37:40 -05:00
var totalGroups [] * pb . Group
2020-06-22 10:46:45 -07:00
for i := 0 ; i < 10 ; i ++ {
2023-12-21 12:54:27 -08:00
gg := iam . TestGroup ( t , conn , "global" )
wantGlobalGroups = append ( wantGlobalGroups , & pb . Group {
Id : gg . GetPublicId (),
ScopeId : gg . GetScopeId (),
Scope : & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : "global" , Description : "Global Scope" },
CreatedTime : gg . GetCreateTime (). GetTimestamp (),
UpdatedTime : gg . GetUpdateTime (). GetTimestamp (),
Version : 1 ,
AuthorizedActions : testAuthorizedActions ,
})
totalGroups = append ( totalGroups , wantGlobalGroups [ i ])
2020-06-29 11:12:40 -07:00
og := iam . TestGroup ( t , conn , oWithGroups . GetPublicId ())
wantOrgGroups = append ( wantOrgGroups , & pb . Group {
2021-01-20 10:53:01 -05:00
Id : og . GetPublicId (),
ScopeId : og . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : oWithGroups . GetPublicId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
CreatedTime : og . GetCreateTime (). GetTimestamp (),
UpdatedTime : og . GetUpdateTime (). GetTimestamp (),
Version : 1 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
})
2021-01-25 19:37:40 -05:00
totalGroups = append ( totalGroups , wantOrgGroups [ i ])
2020-06-29 11:12:40 -07:00
pg := iam . TestGroup ( t , conn , pWithGroups . GetPublicId ())
wantProjGroups = append ( wantProjGroups , & pb . Group {
2021-01-20 10:53:01 -05:00
Id : pg . GetPublicId (),
ScopeId : pg . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pWithGroups . GetPublicId (), Type : scope . Project . String (), ParentScopeId : oNoGroups . GetPublicId ()},
2021-01-20 10:53:01 -05:00
CreatedTime : pg . GetCreateTime (). GetTimestamp (),
UpdatedTime : pg . GetUpdateTime (). GetTimestamp (),
Version : 1 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-22 10:46:45 -07:00
})
2021-01-25 19:37:40 -05:00
totalGroups = append ( totalGroups , wantProjGroups [ i ])
2020-06-22 10:46:45 -07:00
}
2023-12-21 12:54:27 -08:00
slices . Reverse ( wantProjGroups )
slices . Reverse ( wantOrgGroups )
slices . Reverse ( wantGlobalGroups )
slices . Reverse ( totalGroups )
2020-06-22 10:46:45 -07:00
cases := [] struct {
2021-01-25 19:37:40 -05:00
name string
req * pbs . ListGroupsRequest
res * pbs . ListGroupsResponse
err error
2020-06-22 10:46:45 -07:00
}{
{
2023-12-21 12:54:27 -08:00
name : "List Global Groups" ,
req : & pbs . ListGroupsRequest { ScopeId : "global" },
res : & pbs . ListGroupsResponse {
Items : wantGlobalGroups ,
EstItemCount : uint32 ( len ( wantGlobalGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
},
{
name : "List Org Group" ,
2021-01-25 19:37:40 -05:00
req : & pbs . ListGroupsRequest { ScopeId : oWithGroups . GetPublicId ()},
2023-12-21 12:54:27 -08:00
res : & pbs . ListGroupsResponse {
Items : wantOrgGroups ,
EstItemCount : uint32 ( len ( wantOrgGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-01-25 19:37:40 -05:00
},
{
name : "List No Groups" ,
req : & pbs . ListGroupsRequest { ScopeId : oNoGroups . GetPublicId ()},
2023-12-21 12:54:27 -08:00
res : & pbs . ListGroupsResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-01-25 19:37:40 -05:00
},
{
name : "List Many Project Group" ,
req : & pbs . ListGroupsRequest { ScopeId : pWithGroups . GetPublicId ()},
2023-12-21 12:54:27 -08:00
res : & pbs . ListGroupsResponse {
Items : wantProjGroups ,
EstItemCount : uint32 ( len ( wantProjGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-01-25 19:37:40 -05:00
},
{
name : "List No Project Groups" ,
req : & pbs . ListGroupsRequest { ScopeId : pNoGroups . GetPublicId ()},
2023-12-21 12:54:27 -08:00
res : & pbs . ListGroupsResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2020-06-22 10:46:45 -07:00
},
{
2021-01-25 19:37:40 -05:00
name : "List proj groups recursively" ,
req : & pbs . ListGroupsRequest { ScopeId : pWithGroups . GetPublicId (), Recursive : true },
res : & pbs . ListGroupsResponse {
2023-12-21 12:54:27 -08:00
Items : wantProjGroups ,
EstItemCount : uint32 ( len ( wantProjGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
2021-01-25 19:37:40 -05:00
},
2020-06-22 10:46:45 -07:00
},
2020-06-29 11:12:40 -07:00
{
2021-01-25 19:37:40 -05:00
name : "List org groups recursively" ,
req : & pbs . ListGroupsRequest { ScopeId : oNoGroups . GetPublicId (), Recursive : true },
res : & pbs . ListGroupsResponse {
2023-12-21 12:54:27 -08:00
Items : wantProjGroups ,
EstItemCount : uint32 ( len ( wantProjGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
2021-01-25 19:37:40 -05:00
},
2020-06-29 11:12:40 -07:00
},
{
2021-01-25 19:37:40 -05:00
name : "List global groups recursively" ,
req : & pbs . ListGroupsRequest { ScopeId : "global" , Recursive : true },
res : & pbs . ListGroupsResponse {
2023-12-21 12:54:27 -08:00
Items : totalGroups ,
EstItemCount : uint32 ( len ( totalGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
2021-01-25 19:37:40 -05:00
},
2020-06-29 11:12:40 -07:00
},
2021-02-22 10:09:25 -07:00
{
name : "Filter to org groups" ,
req : & pbs . ListGroupsRequest { ScopeId : "global" , Recursive : true , Filter : fmt . Sprintf ( `"/item/scope/id"==%q` , oWithGroups . GetPublicId ())},
2023-12-21 12:54:27 -08:00
res : & pbs . ListGroupsResponse {
Items : wantOrgGroups ,
EstItemCount : uint32 ( len ( wantOrgGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-02-22 10:09:25 -07:00
},
{
name : "Filter to project groups" ,
req : & pbs . ListGroupsRequest { ScopeId : "global" , Recursive : true , Filter : fmt . Sprintf ( `"/item/scope/id"==%q` , pWithGroups . GetPublicId ())},
2023-12-21 12:54:27 -08:00
res : & pbs . ListGroupsResponse {
Items : wantProjGroups ,
EstItemCount : uint32 ( len ( wantProjGroups )),
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-02-22 10:09:25 -07:00
},
{
name : "Filter to no groups" ,
req : & pbs . ListGroupsRequest { ScopeId : "global" , Recursive : true , Filter : `"/item/id"=="doesntmatch"` },
2023-12-21 12:54:27 -08:00
res : & pbs . ListGroupsResponse {
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
},
2021-02-22 10:09:25 -07:00
},
{
name : "Filter Bad Format" ,
req : & pbs . ListGroupsRequest { ScopeId : "global" , Filter : `"//id/"=="bad"` },
err : handlers . InvalidArgumentErrorf ( "bad format" , nil ),
},
2020-06-22 10:46:45 -07:00
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-07-22 00:14:28 -04:00
assert , require := assert . New ( t ), require . New ( t )
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( ctx , repoFn , 1000 )
2020-06-22 10:46:45 -07:00
require . NoError ( err , "Couldn't create new group service." )
2021-05-04 19:57:35 -05:00
// Test with a non-anon user
2021-03-25 03:15:43 -04:00
got , gErr := s . ListGroups ( auth . DisabledAuthTestContext ( repoFn , tc . req . GetScopeId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
2021-01-25 19:37:40 -05:00
assert . True ( errors . Is ( gErr , tc . err ), "ListGroups(%q) got error %v, wanted %v" , tc . req . GetScopeId (), gErr , tc . err )
2021-05-04 19:57:35 -05:00
return
2020-09-23 08:10:27 -07:00
}
2021-05-04 19:57:35 -05:00
require . NoError ( gErr )
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
2023-12-21 12:54:27 -08:00
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
2023-10-31 13:44:17 +00:00
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "ListGroups(%q) got response %q, wanted %q" , tc . req . GetScopeId (), got , tc . res )
2021-05-04 19:57:35 -05:00
// Test the anon case
2022-10-28 15:52:06 -04:00
got , gErr = s . ListGroups ( auth . DisabledAuthTestContext ( repoFn , tc . req . GetScopeId (), auth . WithUserId ( globals . AnonymousUserId )), tc . req )
2021-05-04 19:57:35 -05:00
require . NoError ( gErr )
assert . Len ( got . Items , len ( tc . res . Items ))
for _ , item := range got . GetItems () {
require . Nil ( item . CreatedTime )
require . Nil ( item . Members )
require . Nil ( item . UpdatedTime )
require . Zero ( item . Version )
}
2020-06-22 10:46:45 -07:00
})
}
}
2023-12-21 12:54:27 -08:00
func groupToProto ( u * iam . Group , si * scopes . ScopeInfo , authorizedActions [] string ) * pb . Group {
pu := & pb . Group {
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
Scope : si ,
CreatedTime : u . GetCreateTime (). GetTimestamp (),
UpdatedTime : u . GetUpdateTime (). GetTimestamp (),
Version : u . GetVersion (),
AuthorizedActions : testAuthorizedActions ,
}
if u . GetName () != "" {
pu . Name = wrapperspb . String ( u . GetName ())
}
if u . GetDescription () != "" {
pu . Description = wrapperspb . String ( u . GetDescription ())
}
return pu
}
func TestListPagination ( t * testing . T ) {
// Set database read timeout to avoid duplicates in response
oldReadTimeout := globals . RefreshReadLookbackDuration
globals . RefreshReadLookbackDuration = 0
t . Cleanup ( func () {
globals . RefreshReadLookbackDuration = oldReadTimeout
})
ctx := context . Background ()
conn , _ := db . TestSetup ( t , "postgres" )
sqlDB , err := conn . SqlDB ( ctx )
require . NoError ( t , err )
wrapper := db . TestWrapper ( t )
kms := kms . TestKms ( t , conn , wrapper )
rw := db . New ( conn )
iamRepo := iam . TestRepo ( t , conn , wrapper )
iamRepoFn := func () ( * iam . Repository , error ) {
return iamRepo , nil
}
tokenRepoFn := func () ( * authtoken . Repository , error ) {
return authtoken . NewRepository ( ctx , rw , rw , kms )
}
serversRepoFn := func () ( * server . Repository , error ) {
return server . NewRepository ( ctx , rw , rw , kms )
}
tokenRepo , err := tokenRepoFn ()
require . NoError ( t , err )
// Run analyze to update postgres meta tables
_ , err = sqlDB . ExecContext ( ctx , "analyze" )
require . NoError ( t , err )
oNoGroups , pWithGroups := iam . TestScopes ( t , iamRepo )
oWithGroups , pNoGroups := iam . TestScopes ( t , iamRepo )
authMethod := password . TestAuthMethods ( t , conn , "global" , 1 )[ 0 ]
acct := password . TestAccount ( t , conn , authMethod . GetPublicId (), "test_user" )
u := iam . TestUser ( t , iamRepo , "global" , iam . WithAccountIds ( acct . PublicId ))
// add roles to be able to see all users
allowedRole := iam . TestRole ( t , conn , "global" )
2024-01-17 23:54:49 -08:00
iam . TestRoleGrant ( t , conn , allowedRole . GetPublicId (), "ids=*;type=*;actions=*" )
2023-12-21 12:54:27 -08:00
iam . TestUserRole ( t , conn , allowedRole . GetPublicId (), u . GetPublicId ())
for _ , scope := range [] * iam . Scope { oWithGroups , oNoGroups , pWithGroups , pNoGroups } {
allowedRole := iam . TestRole ( t , conn , scope . GetPublicId ())
2024-01-17 23:54:49 -08:00
iam . TestRoleGrant ( t , conn , allowedRole . GetPublicId (), "ids=*;type=*;actions=*" )
2023-12-21 12:54:27 -08:00
iam . TestUserRole ( t , conn , allowedRole . GetPublicId (), u . GetPublicId ())
}
at , err := tokenRepo . CreateAuthToken ( ctx , u , acct . GetPublicId ())
require . NoError ( t , err )
// Test without anon user
requestInfo := authpb . RequestInfo {
TokenFormat : uint32 ( auth . AuthTokenTypeBearer ),
PublicId : at . GetPublicId (),
Token : at . GetToken (),
}
requestContext := context . WithValue ( context . Background (), requests . ContextRequestInformationKey , & requests . RequestContext {})
ctx = auth . NewVerifierContext ( requestContext , iamRepoFn , tokenRepoFn , serversRepoFn , kms , & requestInfo )
var allGroups [] * pb . Group
var projGroups [] * pb . Group
var orgGroups [] * pb . Group
var globalGroups [] * pb . Group
var safeToDeleteGroup string
globalScopeInfo := & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : "global" , Description : "Global Scope" }
orgScopeInfo := & scopes . ScopeInfo { Id : oWithGroups . GetPublicId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()}
projScopeInfo := & scopes . ScopeInfo { Id : pWithGroups . GetPublicId (), Type : scope . Project . String (), ParentScopeId : pWithGroups . GetParentId ()}
for i := 0 ; i < 10 ; i ++ {
gg := iam . TestGroup ( t , conn , scope . Global . String ())
allGroups = append ( allGroups , groupToProto ( gg , globalScopeInfo , testAuthorizedActions ))
globalGroups = append ( globalGroups , groupToProto ( gg , globalScopeInfo , testAuthorizedActions ))
og := iam . TestGroup ( t , conn , oWithGroups . GetPublicId ())
allGroups = append ( allGroups , groupToProto ( og , orgScopeInfo , testAuthorizedActions ))
orgGroups = append ( orgGroups , groupToProto ( og , orgScopeInfo , testAuthorizedActions ))
pg := iam . TestGroup ( t , conn , pWithGroups . GetPublicId ())
allGroups = append ( allGroups , groupToProto ( pg , projScopeInfo , testAuthorizedActions ))
projGroups = append ( projGroups , groupToProto ( pg , projScopeInfo , testAuthorizedActions ))
safeToDeleteGroup = pg . GetPublicId ()
}
slices . Reverse ( allGroups )
slices . Reverse ( projGroups )
slices . Reverse ( orgGroups )
slices . Reverse ( globalGroups )
a , err := groups . NewService ( ctx , iamRepoFn , 1000 )
require . NoError ( t , err , "Couldn't create new group service." )
// Run analyze to update postgres estimates
_ , err = sqlDB . ExecContext ( context . Background (), "analyze" )
require . NoError ( t , err )
itemCount := uint32 ( len ( allGroups ))
testPageSize := int (( itemCount - 2 ) / 2 )
// Start paginating, recursively
req := & pbs . ListGroupsRequest {
ScopeId : "global" ,
Recursive : true ,
Filter : "" ,
ListToken : "" ,
PageSize : uint32 ( testPageSize ),
}
got , err := a . ListGroups ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), testPageSize )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : allGroups [ 0 : testPageSize ],
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
// In addition to the added groups, there are the groups added
// by the test setup when specifying the permissions of the
// requester
EstItemCount : itemCount ,
},
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . Transform (),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
// Request second page
req . ListToken = got . ListToken
got , err = a . ListGroups ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), testPageSize )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : allGroups [ testPageSize : testPageSize * 2 ],
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
// Request rest of results
req . ListToken = got . ListToken
req . PageSize = 10
got , err = a . ListGroups ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 2 )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : allGroups [ testPageSize * 2 :],
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
// Update 2 groups and see them in the refresh
g1 := allGroups [ len ( allGroups ) - 1 ]
g1 . Description = wrapperspb . String ( "updated1" )
resp1 , err := a . UpdateGroup ( ctx , & pbs . UpdateGroupRequest {
Id : g1 . GetId (),
Item : & pb . Group { Description : g1 . GetDescription (), Version : g1 . GetVersion ()},
UpdateMask : & field_mask . FieldMask { Paths : [] string { "description" }},
})
require . NoError ( t , err )
g1 . UpdatedTime = resp1 . GetItem (). GetUpdatedTime ()
g1 . Version = resp1 . GetItem (). GetVersion ()
allGroups = append ([] * pb . Group { g1 }, allGroups [: len ( allGroups ) - 1 ] ... )
g2 := allGroups [ len ( allGroups ) - 1 ]
g2 . Description = wrapperspb . String ( "updated2" )
resp2 , err := a . UpdateGroup ( ctx , & pbs . UpdateGroupRequest {
Id : g2 . GetId (),
Item : & pb . Group { Description : g2 . GetDescription (), Version : g2 . GetVersion ()},
UpdateMask : & field_mask . FieldMask { Paths : [] string { "description" }},
})
require . NoError ( t , err )
g2 . UpdatedTime = resp2 . GetItem (). GetUpdatedTime ()
g2 . Version = resp2 . GetItem (). GetVersion ()
allGroups = append ([] * pb . Group { g2 }, allGroups [: len ( allGroups ) - 1 ] ... )
// Run analyze to update postgres estimates
_ , err = sqlDB . ExecContext ( ctx , "analyze" )
require . NoError ( t , err )
// Request updated results
req . ListToken = got . ListToken
req . PageSize = 1
got , err = a . ListGroups ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : [] * pb . Group { allGroups [ 0 ]},
ResponseType : "delta" ,
SortBy : "updated_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
// Get next page
req . ListToken = got . ListToken
got , err = a . ListGroups ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
// Compare without comparing the list token
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : [] * pb . Group { allGroups [ 1 ]},
ResponseType : "complete" ,
SortBy : "updated_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
// Request new page with filter requiring looping
// to fill the page.
req . ListToken = ""
req . PageSize = 1
req . Filter = fmt . Sprintf ( `"/item/id"==%q or "/item/id"==%q` , allGroups [ len ( allGroups ) - 2 ]. Id , allGroups [ len ( allGroups ) - 1 ]. Id )
got , err = a . ListGroups ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : [] * pb . Group { allGroups [ len ( allGroups ) - 2 ]},
ResponseType : "delta" ,
SortBy : "created_time" ,
SortDir : "desc" ,
// Should be empty again
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
req . ListToken = got . ListToken
// Get the second page
got , err = a . ListGroups ( ctx , req )
require . NoError ( t , err )
require . Len ( t , got . GetItems (), 1 )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : [] * pb . Group { allGroups [ len ( allGroups ) - 1 ]},
ResponseType : "complete" ,
SortBy : "created_time" ,
SortDir : "desc" ,
RemovedIds : nil ,
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
_ , err = iamRepo . DeleteGroup ( ctx , safeToDeleteGroup )
require . NoError ( t , err )
req . ListToken = got . ListToken
got , err = a . ListGroups ( ctx , req )
require . NoError ( t , err )
assert . Empty ( t ,
cmp . Diff (
got ,
& pbs . ListGroupsResponse {
Items : nil ,
ResponseType : "complete" ,
SortBy : "updated_time" ,
SortDir : "desc" ,
RemovedIds : [] string { safeToDeleteGroup },
EstItemCount : itemCount ,
},
protocmp . Transform (),
protocmp . SortRepeated ( func ( a , b string ) bool {
return strings . Compare ( a , b ) < 0
}),
protocmp . IgnoreFields ( & pbs . ListGroupsResponse {}, "list_token" ),
),
)
2024-02-15 09:26:29 -08:00
// Create unauthenticated user
unauthAt := authtoken . TestAuthToken ( t , conn , kms , oWithGroups . GetPublicId ())
unauthR := iam . TestRole ( t , conn , pWithGroups . GetPublicId ())
_ = iam . TestUserRole ( t , conn , unauthR . GetPublicId (), unauthAt . GetIamUserId ())
// Make a request with the unauthenticated user,
// ensure the response is 403 forbidden.
requestInfo = authpb . RequestInfo {
TokenFormat : uint32 ( auth . AuthTokenTypeBearer ),
PublicId : unauthAt . GetPublicId (),
Token : unauthAt . GetToken (),
}
requestContext = context . WithValue ( context . Background (), requests . ContextRequestInformationKey , & requests . RequestContext {})
ctx = auth . NewVerifierContext ( requestContext , iamRepoFn , tokenRepoFn , serversRepoFn , kms , & requestInfo )
_ , err = a . ListGroups ( ctx , & pbs . ListGroupsRequest {
ScopeId : "global" ,
Recursive : true ,
})
require . Error ( t , err )
assert . Equal ( t , handlers . ForbiddenError (), err )
2023-12-21 12:54:27 -08:00
}
2020-06-15 15:22:41 -07:00
func TestDelete ( t * testing . T ) {
2021-03-25 03:15:43 -04:00
og , pg , repoFn := createDefaultGroupsAndRepo ( t )
2020-06-15 15:22:41 -07:00
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( context . Background (), repoFn , 1000 )
2020-09-23 08:10:27 -07:00
require . NoError ( t , err , "Error when getting new group service." )
2020-06-15 15:22:41 -07:00
cases := [] struct {
name string
2020-07-22 00:14:28 -04:00
scopeId string
2020-06-15 15:22:41 -07:00
req * pbs . DeleteGroupRequest
res * pbs . DeleteGroupResponse
2020-09-23 08:10:27 -07:00
err error
2020-06-15 15:22:41 -07:00
}{
{
2020-07-22 00:14:28 -04:00
name : "Delete an Existing Group" ,
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . DeleteGroupRequest {
2020-07-22 00:14:28 -04:00
Id : og . GetPublicId (),
2020-06-15 15:22:41 -07:00
},
},
{
2020-07-22 00:14:28 -04:00
name : "Delete bad group id" ,
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . DeleteGroupRequest {
2023-03-10 15:06:39 -05:00
Id : globals . GroupPrefix + "_doesntexis" ,
2020-06-15 15:22:41 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-15 15:22:41 -07:00
},
{
2020-07-22 00:14:28 -04:00
name : "Bad Group Id formatting" ,
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . DeleteGroupRequest {
2020-07-22 00:14:28 -04:00
Id : "bad_format" ,
2020-06-15 15:22:41 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
2020-07-22 00:14:28 -04:00
name : "Project Scoped Delete an Existing Group" ,
scopeId : pg . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . DeleteGroupRequest {
2020-07-22 00:14:28 -04:00
Id : pg . GetPublicId (),
2020-06-29 11:12:40 -07:00
},
},
{
2020-07-22 00:14:28 -04:00
name : "Project Scoped Delete bad group id" ,
scopeId : pg . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . DeleteGroupRequest {
2023-03-10 15:06:39 -05:00
Id : globals . GroupPrefix + "_doesntexis" ,
2020-06-29 11:12:40 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-29 11:12:40 -07:00
},
2020-06-15 15:22:41 -07:00
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
got , gErr := s . DeleteGroup ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "DeleteGroup(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-22 00:14:28 -04:00
assert . EqualValuesf ( tc . res , got , "DeleteGroup(%+v) got response %q, wanted %q" , tc . req , got , tc . res )
2020-06-15 15:22:41 -07:00
})
}
}
func TestDelete_twice ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
og , pg , repoFn := createDefaultGroupsAndRepo ( t )
2020-06-15 15:22:41 -07:00
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( context . Background (), repoFn , 1000 )
2020-06-15 15:22:41 -07:00
require . NoError ( err , "Error when getting new group service" )
2020-07-22 00:14:28 -04:00
scopeId := og . GetScopeId ()
2020-06-15 15:22:41 -07:00
req := & pbs . DeleteGroupRequest {
2020-07-22 00:14:28 -04:00
Id : og . GetPublicId (),
2020-06-15 15:22:41 -07:00
}
2021-03-25 03:15:43 -04:00
ctx := auth . DisabledAuthTestContext ( repoFn , scopeId )
2020-09-08 23:57:26 -04:00
_ , gErr := s . DeleteGroup ( ctx , req )
2020-06-15 15:22:41 -07:00
assert . NoError ( gErr , "First attempt" )
2020-09-08 23:57:26 -04:00
_ , gErr = s . DeleteGroup ( ctx , req )
2020-09-04 14:48:11 -07:00
assert . Error ( gErr , "Second attempt" )
2020-09-23 08:10:27 -07:00
assert . True ( errors . Is ( gErr , handlers . ApiErrorWithCode ( codes . NotFound )), "Expected permission denied for the second delete." )
2020-06-29 11:12:40 -07:00
2020-07-22 00:14:28 -04:00
scopeId = pg . GetScopeId ()
2020-06-29 11:12:40 -07:00
projReq := & pbs . DeleteGroupRequest {
2020-07-22 00:14:28 -04:00
Id : pg . GetPublicId (),
2020-06-29 11:12:40 -07:00
}
2021-03-25 03:15:43 -04:00
ctx = auth . DisabledAuthTestContext ( repoFn , scopeId )
2020-09-08 23:57:26 -04:00
_ , gErr = s . DeleteGroup ( ctx , projReq )
2020-06-29 11:12:40 -07:00
assert . NoError ( gErr , "First attempt" )
2020-09-08 23:57:26 -04:00
_ , gErr = s . DeleteGroup ( ctx , projReq )
2020-09-04 14:48:11 -07:00
assert . Error ( gErr , "Second attempt" )
2020-09-23 08:10:27 -07:00
assert . True ( errors . Is ( gErr , handlers . ApiErrorWithCode ( codes . NotFound )), "Expected permission denied for the second delete." )
2020-06-15 15:22:41 -07:00
}
func TestCreate ( t * testing . T ) {
2021-03-25 03:15:43 -04:00
defaultOGroup , defaultPGroup , repoFn := createDefaultGroupsAndRepo ( t )
2021-04-23 09:13:37 -05:00
defaultCreated := defaultOGroup . GetCreateTime (). GetTimestamp (). AsTime ()
2020-07-22 00:14:28 -04:00
toMerge := & pbs . CreateGroupRequest {}
2020-06-15 15:22:41 -07:00
cases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . CreateGroupRequest
res * pbs . CreateGroupResponse
err error
2020-06-15 15:22:41 -07:00
}{
{
2020-09-02 19:43:41 -07:00
name : "Create a valid Group" ,
2020-06-15 15:22:41 -07:00
req : & pbs . CreateGroupRequest { Item : & pb . Group {
2020-09-02 19:43:41 -07:00
ScopeId : defaultOGroup . GetScopeId (),
2020-06-15 15:22:41 -07:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
}},
res : & pbs . CreateGroupResponse {
2023-03-10 15:06:39 -05:00
Uri : fmt . Sprintf ( "groups/%s_" , globals . GroupPrefix ),
2020-06-29 11:12:40 -07:00
Item : & pb . Group {
2021-01-20 10:53:01 -05:00
ScopeId : defaultOGroup . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : defaultOGroup . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
Version : 1 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
},
},
},
2020-09-03 08:02:30 -07:00
{
name : "Create a global Group" ,
req : & pbs . CreateGroupRequest { Item : & pb . Group {
ScopeId : scope . Global . String (),
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
}},
res : & pbs . CreateGroupResponse {
2023-03-10 15:06:39 -05:00
Uri : fmt . Sprintf ( "groups/%s_" , globals . GroupPrefix ),
2020-09-03 08:02:30 -07:00
Item : & pb . Group {
2021-01-20 10:53:01 -05:00
ScopeId : scope . Global . String (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : scope . Global . String (), Type : scope . Global . String (), Name : scope . Global . String (), Description : "Global Scope" },
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
Version : 1 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-09-03 08:02:30 -07:00
},
},
},
2020-06-29 11:12:40 -07:00
{
2020-09-02 19:43:41 -07:00
name : "Create a valid Project Scoped Group" ,
2020-06-29 11:12:40 -07:00
req : & pbs . CreateGroupRequest {
Item : & pb . Group {
2020-09-02 19:43:41 -07:00
ScopeId : defaultPGroup . GetScopeId (),
2020-06-29 11:12:40 -07:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . CreateGroupResponse {
2023-03-10 15:06:39 -05:00
Uri : fmt . Sprintf ( "groups/%s_" , globals . GroupPrefix ),
2020-06-15 15:22:41 -07:00
Item : & pb . Group {
2021-01-20 10:53:01 -05:00
ScopeId : defaultPGroup . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : defaultPGroup . GetScopeId (), Type : scope . Project . String (), ParentScopeId : defaultOGroup . GetScopeId ()},
2021-01-20 10:53:01 -05:00
Name : & wrapperspb . StringValue { Value : "name" },
Description : & wrapperspb . StringValue { Value : "desc" },
Version : 1 ,
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-15 15:22:41 -07:00
},
},
},
{
name : "Can't specify Id" ,
req : & pbs . CreateGroupRequest { Item : & pb . Group {
2023-03-10 15:06:39 -05:00
Id : globals . GroupPrefix + "_notallowed" ,
2020-06-15 15:22:41 -07:00
}},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
name : "Can't specify Created Time" ,
req : & pbs . CreateGroupRequest { Item : & pb . Group {
2021-04-23 09:13:37 -05:00
CreatedTime : timestamppb . Now (),
2020-06-15 15:22:41 -07:00
}},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
name : "Can't specify Update Time" ,
req : & pbs . CreateGroupRequest { Item : & pb . Group {
2021-04-23 09:13:37 -05:00
UpdatedTime : timestamppb . Now (),
2020-06-15 15:22:41 -07:00
}},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-15 15:22:41 -07:00
req := proto . Clone ( toMerge ).( * pbs . CreateGroupRequest )
proto . Merge ( req , tc . req )
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( context . Background (), repoFn , 1000 )
2020-06-15 15:22:41 -07:00
require . NoError ( err , "Error when getting new group service." )
2021-03-25 03:15:43 -04:00
got , gErr := s . CreateGroup ( auth . DisabledAuthTestContext ( repoFn , req . GetItem (). GetScopeId ()), req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "CreateGroup(%+v) got error %v, wanted %v" , req , gErr , tc . err )
}
2020-06-15 15:22:41 -07:00
if got != nil {
2020-08-05 10:19:55 -07:00
assert . Contains ( got . GetUri (), tc . res . Uri )
2023-03-10 15:06:39 -05:00
assert . True ( strings . HasPrefix ( got . GetItem (). GetId (), globals . GroupPrefix + "_" ))
2021-04-23 09:13:37 -05:00
gotCreateTime := got . GetItem (). GetCreatedTime (). AsTime ()
gotUpdateTime := got . GetItem (). GetUpdatedTime (). AsTime ()
2020-06-15 15:22:41 -07:00
// Verify it is a group created after the test setup's default group
assert . True ( gotCreateTime . After ( defaultCreated ), "New group should have been created after default group. Was created %v, which is after %v" , gotCreateTime , defaultCreated )
assert . True ( gotUpdateTime . After ( defaultCreated ), "New group should have been updated after default group. Was updated %v, which is after %v" , gotUpdateTime , defaultCreated )
// Clear all values which are hard to compare against.
got . Uri , tc . res . Uri = "" , ""
got . Item . Id , tc . res . Item . Id = "" , ""
got . Item . CreatedTime , got . Item . UpdatedTime , tc . res . Item . CreatedTime , tc . res . Item . UpdatedTime = nil , nil , nil , nil
}
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "CreateGroup(%q) got response %q, wanted %q" , req , got , tc . res )
2020-06-15 15:22:41 -07:00
})
}
}
func TestUpdate ( t * testing . T ) {
2023-06-06 17:09:08 -04:00
ctx := context . Background ()
2020-07-22 15:10:21 -07:00
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-22 15:10:21 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-22 15:10:21 -07:00
}
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
u := iam . TestUser ( t , iamRepo , o . GetPublicId ())
2020-07-22 15:10:21 -07:00
og := iam . TestGroup ( t , conn , o . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
_ = iam . TestGroupMember ( t , conn , og . GetPublicId (), u . GetPublicId ())
pg := iam . TestGroup ( t , conn , p . GetPublicId (), iam . WithDescription ( "default" ), iam . WithName ( "default" ))
_ = iam . TestGroupMember ( t , conn , pg . GetPublicId (), u . GetPublicId ())
2020-06-15 15:22:41 -07:00
2020-08-07 12:55:02 -04:00
var ogVersion uint32 = 1
var pgVersion uint32 = 1
resetGroups := func ( proj bool ) {
2020-06-15 15:22:41 -07:00
repo , err := repoFn ()
2020-09-23 08:10:27 -07:00
require . NoError ( t , err , "Couldn't get a new repo" )
2020-08-07 12:55:02 -04:00
if proj {
pgVersion ++
2023-06-06 17:09:08 -04:00
pg , _ , _ , err = repo . UpdateGroup ( ctx , pg , pgVersion , [] string { "Name" , "Description" })
2020-09-23 08:10:27 -07:00
require . NoError ( t , err , "Failed to reset the group" )
2020-08-07 12:55:02 -04:00
pgVersion ++
} else {
ogVersion ++
2023-06-06 17:09:08 -04:00
og , _ , _ , err = repo . UpdateGroup ( ctx , og , ogVersion , [] string { "Name" , "Description" })
2020-09-23 08:10:27 -07:00
require . NoError ( t , err , "Failed to reset the group" )
2020-08-07 12:55:02 -04:00
ogVersion ++
}
2020-06-15 15:22:41 -07:00
}
2021-04-23 09:13:37 -05:00
created := og . GetCreateTime (). GetTimestamp (). AsTime ()
2020-06-15 15:22:41 -07:00
toMerge := & pbs . UpdateGroupRequest {
2020-07-22 00:14:28 -04:00
Id : og . GetPublicId (),
2020-06-15 15:22:41 -07:00
}
2023-12-21 12:54:27 -08:00
tested , err := groups . NewService ( ctx , repoFn , 1000 )
2020-11-02 07:01:37 -08:00
require . NoError ( t , err , "Error creating new service" )
2020-06-15 15:22:41 -07:00
cases := [] struct {
name string
2020-07-22 00:14:28 -04:00
scopeId string
2020-06-15 15:22:41 -07:00
req * pbs . UpdateGroupRequest
res * pbs . UpdateGroupResponse
2020-09-23 08:10:27 -07:00
err error
2020-06-15 15:22:41 -07:00
}{
{
2020-07-22 00:14:28 -04:00
name : "Update an Existing Group" ,
2020-07-22 15:10:21 -07:00
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" , "description" },
},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . UpdateGroupResponse {
Item : & pb . Group {
2020-06-29 11:12:40 -07:00
Id : og . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : og . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : og . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2020-06-29 11:12:40 -07:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
CreatedTime : og . GetCreateTime (). GetTimestamp (),
2020-07-22 15:10:21 -07:00
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Multiple Paths in single string" ,
2020-07-22 15:10:21 -07:00
scopeId : og . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name,description" },
},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . UpdateGroupResponse {
Item : & pb . Group {
Id : og . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : og . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : og . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2020-06-29 11:12:40 -07:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
CreatedTime : og . GetCreateTime (). GetTimestamp (),
2020-07-22 15:10:21 -07:00
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-29 11:12:40 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Update an Existing Project Scoped Group" ,
2020-07-22 15:10:21 -07:00
scopeId : pg . GetScopeId (),
2020-06-29 11:12:40 -07:00
req : & pbs . UpdateGroupRequest {
2020-07-22 00:14:28 -04:00
Id : pg . GetPublicId (),
2020-06-29 11:12:40 -07:00
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" , "description" },
},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . UpdateGroupResponse {
Item : & pb . Group {
Id : pg . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : pg . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pg . GetScopeId (), Type : scope . Project . String (), ParentScopeId : og . GetScopeId ()},
2020-06-15 15:22:41 -07:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
2020-06-29 11:12:40 -07:00
CreatedTime : pg . GetCreateTime (). GetTimestamp (),
2020-07-22 15:10:21 -07:00
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-15 15:22:41 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Multiple Paths in single string" ,
2020-07-22 15:10:21 -07:00
scopeId : pg . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . UpdateGroupRequest {
2020-07-22 00:14:28 -04:00
Id : pg . GetPublicId (),
2020-06-15 15:22:41 -07:00
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name,description" },
},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
res : & pbs . UpdateGroupResponse {
Item : & pb . Group {
2020-06-29 11:12:40 -07:00
Id : pg . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : pg . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : pg . GetScopeId (), Type : scope . Project . String (), ParentScopeId : og . GetScopeId ()},
2020-06-15 15:22:41 -07:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
2020-06-29 11:12:40 -07:00
CreatedTime : pg . GetCreateTime (). GetTimestamp (),
2020-07-22 15:10:21 -07:00
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-15 15:22:41 -07:00
},
},
},
{
name : "No Update Mask" ,
req : & pbs . UpdateGroupRequest {
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "updated name" },
Description : & wrapperspb . StringValue { Value : "updated desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
2020-07-22 00:14:28 -04:00
name : "No Paths in Mask" ,
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask { Paths : [] string {}},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "updated name" },
Description : & wrapperspb . StringValue { Value : "updated desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
2024-02-16 08:30:16 -05:00
name : "Only non-existent paths in Mask" ,
2020-07-22 00:14:28 -04:00
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . UpdateGroupRequest {
2024-02-16 08:30:16 -05:00
UpdateMask : & field_mask . FieldMask { Paths : [] string { "nonexistent_field" }},
2020-06-15 15:22:41 -07:00
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "updated name" },
Description : & wrapperspb . StringValue { Value : "updated desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
2020-07-22 00:14:28 -04:00
name : "Unset Name" ,
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" },
},
Item : & pb . Group {
Description : & wrapperspb . StringValue { Value : "ignored" },
},
},
res : & pbs . UpdateGroupResponse {
Item : & pb . Group {
2020-06-29 11:12:40 -07:00
Id : og . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : og . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : og . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2020-06-15 15:22:41 -07:00
Description : & wrapperspb . StringValue { Value : "default" },
2020-06-29 11:12:40 -07:00
CreatedTime : og . GetCreateTime (). GetTimestamp (),
2020-07-22 15:10:21 -07:00
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-15 15:22:41 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Update Only Name" ,
2020-07-22 15:10:21 -07:00
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "name" },
},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "updated" },
Description : & wrapperspb . StringValue { Value : "ignored" },
},
},
res : & pbs . UpdateGroupResponse {
Item : & pb . Group {
2020-06-29 11:12:40 -07:00
Id : og . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : og . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : og . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2020-06-15 15:22:41 -07:00
Name : & wrapperspb . StringValue { Value : "updated" },
Description : & wrapperspb . StringValue { Value : "default" },
2020-06-29 11:12:40 -07:00
CreatedTime : og . GetCreateTime (). GetTimestamp (),
2020-07-22 15:10:21 -07:00
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-15 15:22:41 -07:00
},
},
},
{
2020-07-22 00:14:28 -04:00
name : "Update Only Description" ,
2020-07-22 15:10:21 -07:00
scopeId : og . GetScopeId (),
2020-06-15 15:22:41 -07:00
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "description" },
},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "ignored" },
Description : & wrapperspb . StringValue { Value : "notignored" },
},
},
res : & pbs . UpdateGroupResponse {
Item : & pb . Group {
2020-06-29 11:12:40 -07:00
Id : og . GetPublicId (),
2020-09-02 19:43:41 -07:00
ScopeId : og . GetScopeId (),
2021-03-25 03:15:43 -04:00
Scope : & scopes . ScopeInfo { Id : og . GetScopeId (), Type : scope . Org . String (), ParentScopeId : scope . Global . String ()},
2020-06-15 15:22:41 -07:00
Name : & wrapperspb . StringValue { Value : "default" },
Description : & wrapperspb . StringValue { Value : "notignored" },
2020-06-29 11:12:40 -07:00
CreatedTime : og . GetCreateTime (). GetTimestamp (),
2020-07-22 15:10:21 -07:00
MemberIds : [] string { u . GetPublicId ()},
Members : [] * pb . Member {
{
Id : u . GetPublicId (),
ScopeId : u . GetScopeId (),
},
},
2021-04-23 09:13:37 -05:00
AuthorizedActions : testAuthorizedActions ,
2020-06-15 15:22:41 -07:00
},
},
},
{
name : "Update a Non Existing Group" ,
req : & pbs . UpdateGroupRequest {
2023-03-10 15:06:39 -05:00
Id : globals . GroupPrefix + "_DoesntExis" ,
2020-06-15 15:22:41 -07:00
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "description" },
},
Item : & pb . Group {
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "desc" },
},
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . NotFound ),
2020-06-15 15:22:41 -07:00
},
{
name : "Cant change Id" ,
req : & pbs . UpdateGroupRequest {
2020-06-29 11:12:40 -07:00
Id : og . GetPublicId (),
2020-06-15 15:22:41 -07:00
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "id" },
},
Item : & pb . Group {
2023-03-10 15:06:39 -05:00
Id : globals . GroupPrefix + "_somethinge" ,
2020-06-15 15:22:41 -07:00
Name : & wrapperspb . StringValue { Value : "new" },
Description : & wrapperspb . StringValue { Value : "new desc" },
2021-01-07 10:02:32 -05:00
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
name : "Cant specify Created Time" ,
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "created_time" },
},
Item : & pb . Group {
2021-04-23 09:13:37 -05:00
CreatedTime : timestamppb . Now (),
2020-06-15 15:22:41 -07:00
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
{
name : "Cant specify Updated Time" ,
req : & pbs . UpdateGroupRequest {
UpdateMask : & field_mask . FieldMask {
Paths : [] string { "updated_time" },
},
Item : & pb . Group {
2021-04-23 09:13:37 -05:00
UpdatedTime : timestamppb . Now (),
2020-06-15 15:22:41 -07:00
},
},
2020-09-23 08:10:27 -07:00
res : nil ,
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-06-15 15:22:41 -07:00
},
}
for _ , tc := range cases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-08-07 12:55:02 -04:00
ver := ogVersion
if tc . req . Id == pg . PublicId {
ver = pgVersion
}
2020-08-18 17:38:38 -07:00
tc . req . Item . Version = ver
2020-08-07 12:55:02 -04:00
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2020-06-15 15:22:41 -07:00
req := proto . Clone ( toMerge ).( * pbs . UpdateGroupRequest )
proto . Merge ( req , tc . req )
2020-08-07 12:55:02 -04:00
// Test with bad version (too high, too low)
2020-08-18 17:38:38 -07:00
req . Item . Version = ver + 2
2021-03-25 03:15:43 -04:00
_ , gErr := tested . UpdateGroup ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
2020-08-07 12:55:02 -04:00
require . Error ( gErr )
2020-08-18 17:38:38 -07:00
req . Item . Version = ver - 1
2021-03-25 03:15:43 -04:00
_ , gErr = tested . UpdateGroup ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
2020-08-07 12:55:02 -04:00
require . Error ( gErr )
2020-08-18 17:38:38 -07:00
req . Item . Version = ver
2020-08-07 12:55:02 -04:00
2021-03-25 03:15:43 -04:00
got , gErr := tested . UpdateGroup ( auth . DisabledAuthTestContext ( repoFn , tc . scopeId ), req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "UpdateGroup(%+v) got error %v, wanted %v" , req , gErr , tc . err )
}
2020-06-15 15:22:41 -07:00
2020-09-23 08:10:27 -07:00
if tc . err == nil {
2020-08-07 12:55:02 -04:00
defer resetGroups ( req . Id == pg . PublicId )
}
2020-06-15 15:22:41 -07:00
if got != nil {
assert . NotNilf ( tc . res , "Expected UpdateGroup response to be nil, but was %v" , got )
2021-04-23 09:13:37 -05:00
gotUpdateTime := got . GetItem (). GetUpdatedTime (). AsTime ()
2020-06-15 15:22:41 -07:00
// Verify it is a group updated after it was created
assert . True ( gotUpdateTime . After ( created ), "Updated group should have been updated after it's creation. Was updated %v, which is after %v" , gotUpdateTime , created )
// Clear all values which are hard to compare against.
got . Item . UpdatedTime , tc . res . Item . UpdatedTime = nil , nil
2020-08-07 12:55:02 -04:00
assert . Equal ( ver + 1 , got . GetItem (). GetVersion ())
tc . res . Item . Version = ver + 1
2020-06-15 15:22:41 -07:00
}
2023-10-31 13:44:17 +00:00
assert . Empty ( cmp . Diff (
got ,
tc . res ,
protocmp . Transform (),
cmpopts . SortSlices ( func ( a , b string ) bool {
return a < b
}),
), "UpdateGroup(%q) got response %q, wanted %q" , req , got , tc . res )
2020-07-22 15:10:21 -07:00
})
}
}
func TestAddMember ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-22 15:10:21 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-22 15:10:21 -07:00
}
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( context . Background (), repoFn , 100 )
2020-07-22 15:10:21 -07:00
require . NoError ( t , err , "Error when getting new group service." )
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2020-07-22 15:10:21 -07:00
users := [] * iam . User {
2020-08-19 16:47:18 -04:00
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
2020-07-22 15:10:21 -07:00
}
addCases := [] struct {
name string
setup func ( * iam . Group )
addUsers [] string
addGroups [] string
resultUsers [] string
resultGroups [] string
wantErr bool
}{
{
name : "Add user on empty group" ,
setup : func ( g * iam . Group ) {},
addUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
},
{
name : "Add user on populated group" ,
setup : func ( g * iam . Group ) {
iam . TestGroupMember ( t , conn , g . GetPublicId (), users [ 0 ]. GetPublicId ())
},
addUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 0 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
},
2020-10-02 16:45:32 -07:00
{
name : "Add duplicate user on populated group" ,
setup : func ( g * iam . Group ) {
iam . TestGroupMember ( t , conn , g . GetPublicId (), users [ 0 ]. GetPublicId ())
},
addUsers : [] string { users [ 1 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 0 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
},
2020-07-22 15:10:21 -07:00
{
name : "Add empty on populated group" ,
setup : func ( g * iam . Group ) {
iam . TestGroupMember ( t , conn , g . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestGroupMember ( t , conn , g . GetPublicId (), users [ 1 ]. GetPublicId ())
},
wantErr : true ,
},
2020-08-20 13:34:03 -04:00
{
name : "Add invalid u_recovery to group" ,
setup : func ( g * iam . Group ) {},
2022-10-28 15:52:06 -04:00
addUsers : [] string { globals . RecoveryUserId },
2020-08-20 13:34:03 -04:00
wantErr : true ,
},
2020-07-22 15:10:21 -07:00
}
for _ , tc := range addCases {
for _ , scp := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scp . GetType (), func ( t * testing . T ) {
grp := iam . TestGroup ( t , conn , scp . GetPublicId ())
tc . setup ( grp )
req := & pbs . AddGroupMembersRequest {
2020-08-18 17:38:38 -07:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
MemberIds : tc . addUsers ,
2020-07-22 15:10:21 -07:00
}
2021-03-25 03:15:43 -04:00
got , err := s . AddGroupMembers ( auth . DisabledAuthTestContext ( repoFn , scp . GetPublicId ()), req )
2020-07-22 15:10:21 -07:00
if tc . wantErr {
assert . Error ( t , err )
return
}
s , ok := status . FromError ( err )
require . True ( t , ok )
require . NoError ( t , err , "Got error: %v" , s )
assert . True ( t , equalMembers ( got . GetItem (), tc . resultUsers ))
})
}
}
grp := iam . TestGroup ( t , conn , p . GetPublicId ())
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . AddGroupMembersRequest
err error
2020-07-22 15:10:21 -07:00
}{
{
name : "Bad Group Id" ,
req : & pbs . AddGroupMembersRequest {
Id : "bad id" ,
2020-08-07 12:55:02 -04:00
Version : grp . GetVersion (),
2020-07-22 15:10:21 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-22 15:10:21 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Invalid user id in member list" ,
req : & pbs . AddGroupMembersRequest {
2020-10-06 13:17:28 -04:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
2020-10-02 16:45:32 -07:00
MemberIds : [] string { "invalid" },
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "u_recovery" ,
req : & pbs . AddGroupMembersRequest {
2020-10-06 13:17:28 -04:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
2022-10-28 15:52:06 -04:00
MemberIds : [] string { globals . RecoveryUserId },
2020-10-02 16:45:32 -07:00
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-22 15:10:21 -07:00
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . AddGroupMembers ( auth . DisabledAuthTestContext ( repoFn , grp . GetScopeId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "AddGroupMembers(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-22 15:10:21 -07:00
})
}
}
func TestSetMember ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-22 15:10:21 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-22 15:10:21 -07:00
}
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( context . Background (), repoFn , 1000 )
2020-07-22 15:10:21 -07:00
require . NoError ( t , err , "Error when getting new group service." )
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2020-07-22 15:10:21 -07:00
users := [] * iam . User {
2020-08-19 16:47:18 -04:00
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
2020-07-22 15:10:21 -07:00
}
setCases := [] struct {
name string
setup func ( * iam . Group )
setUsers [] string
setGroups [] string
resultUsers [] string
resultGroups [] string
wantErr bool
}{
{
name : "Set user on empty group" ,
setup : func ( r * iam . Group ) {},
setUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
},
{
name : "Set user on populated group" ,
setup : func ( r * iam . Group ) {
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
},
setUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
},
2020-10-02 16:45:32 -07:00
{
name : "Set duplicate user on populated group" ,
setup : func ( r * iam . Group ) {
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
},
setUsers : [] string { users [ 1 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
},
2020-07-22 15:10:21 -07:00
{
name : "Set empty on populated group" ,
setup : func ( r * iam . Group ) {
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
},
setUsers : [] string {},
resultUsers : nil ,
},
}
for _ , tc := range setCases {
for _ , scp := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scp . GetType (), func ( t * testing . T ) {
grp := iam . TestGroup ( t , conn , scp . GetPublicId ())
tc . setup ( grp )
req := & pbs . SetGroupMembersRequest {
2020-08-18 17:38:38 -07:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
MemberIds : tc . setUsers ,
2020-07-22 15:10:21 -07:00
}
2021-03-25 03:15:43 -04:00
got , err := s . SetGroupMembers ( auth . DisabledAuthTestContext ( repoFn , scp . GetPublicId ()), req )
2020-07-22 15:10:21 -07:00
if tc . wantErr {
assert . Error ( t , err )
return
}
s , ok := status . FromError ( err )
require . True ( t , ok )
require . NoError ( t , err , "Got error: %v" , s )
assert . True ( t , equalMembers ( got . GetItem (), append ( tc . resultUsers , tc . resultGroups ... )))
})
}
}
grp := iam . TestGroup ( t , conn , p . GetPublicId ())
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
req * pbs . SetGroupMembersRequest
err error
2020-07-22 15:10:21 -07:00
}{
{
name : "Bad Group Id" ,
req : & pbs . SetGroupMembersRequest {
Id : "bad id" ,
2020-08-07 12:55:02 -04:00
Version : grp . GetVersion (),
2020-07-22 15:10:21 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-22 15:10:21 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Invalid user id in member list" ,
req : & pbs . SetGroupMembersRequest {
2020-10-06 13:17:28 -04:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
2020-10-02 16:45:32 -07:00
MemberIds : [] string { "invalid" },
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
{
name : "u_recovery" ,
req : & pbs . SetGroupMembersRequest {
2020-10-06 13:17:28 -04:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
2022-10-28 15:52:06 -04:00
MemberIds : [] string { globals . RecoveryUserId },
2020-10-02 16:45:32 -07:00
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-22 15:10:21 -07:00
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . SetGroupMembers ( auth . DisabledAuthTestContext ( repoFn , grp . GetScopeId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
assert . True ( errors . Is ( gErr , tc . err ), "SetGroupMembers(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
}
2020-07-22 15:10:21 -07:00
})
}
}
func TestRemoveMember ( t * testing . T ) {
conn , _ := db . TestSetup ( t , "postgres" )
wrap := db . TestWrapper ( t )
2020-08-19 16:47:18 -04:00
iamRepo := iam . TestRepo ( t , conn , wrap )
2020-07-22 15:10:21 -07:00
repoFn := func () ( * iam . Repository , error ) {
2020-08-19 16:47:18 -04:00
return iamRepo , nil
2020-07-22 15:10:21 -07:00
}
2023-12-21 12:54:27 -08:00
s , err := groups . NewService ( context . Background (), repoFn , 1000 )
2020-07-22 15:10:21 -07:00
require . NoError ( t , err , "Error when getting new grp service." )
2020-08-19 16:47:18 -04:00
o , p := iam . TestScopes ( t , iamRepo )
2020-07-22 15:10:21 -07:00
users := [] * iam . User {
2020-08-19 16:47:18 -04:00
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
iam . TestUser ( t , iamRepo , o . GetPublicId ()),
2020-07-22 15:10:21 -07:00
}
addCases := [] struct {
name string
setup func ( * iam . Group )
removeUsers [] string
removeGroups [] string
resultUsers [] string
resultGroups [] string
wantErr bool
}{
{
name : "Remove user on empty group" ,
setup : func ( r * iam . Group ) {},
removeUsers : [] string { users [ 1 ]. GetPublicId ()},
wantErr : true ,
},
{
name : "Remove 1 of 2 users from group" ,
setup : func ( r * iam . Group ) {
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
},
removeUsers : [] string { users [ 1 ]. GetPublicId ()},
resultUsers : [] string { users [ 0 ]. GetPublicId ()},
},
{
name : "Remove all users from group" ,
setup : func ( r * iam . Group ) {
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
},
removeUsers : [] string { users [ 0 ]. GetPublicId (), users [ 1 ]. GetPublicId ()},
resultUsers : [] string {},
},
2020-10-02 16:45:32 -07:00
{
name : "Remove duplicate user from group" ,
setup : func ( r * iam . Group ) {
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 1 ]. GetPublicId ())
},
removeUsers : [] string { users [ 0 ]. GetPublicId (), users [ 0 ]. GetPublicId ()},
resultUsers : [] string { users [ 1 ]. GetPublicId ()},
},
2020-07-22 15:10:21 -07:00
{
name : "Remove empty on populated group" ,
setup : func ( r * iam . Group ) {
iam . TestGroupMember ( t , conn , r . GetPublicId (), users [ 0 ]. GetPublicId ())
},
wantErr : true ,
},
}
for _ , tc := range addCases {
for _ , scp := range [] * iam . Scope { o , p } {
t . Run ( tc . name + "_" + scp . GetType (), func ( t * testing . T ) {
grp := iam . TestGroup ( t , conn , scp . GetPublicId ())
tc . setup ( grp )
req := & pbs . RemoveGroupMembersRequest {
2020-08-18 17:38:38 -07:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
MemberIds : tc . removeUsers ,
2020-07-22 15:10:21 -07:00
}
2021-03-25 03:15:43 -04:00
got , err := s . RemoveGroupMembers ( auth . DisabledAuthTestContext ( repoFn , scp . GetPublicId ()), req )
2020-07-22 15:10:21 -07:00
if tc . wantErr {
assert . Error ( t , err )
return
}
s , ok := status . FromError ( err )
require . True ( t , ok )
require . NoError ( t , err , "Got error: %v" , s )
assert . True ( t , equalMembers ( got . GetItem (), tc . resultUsers ))
})
}
}
grp := iam . TestGroup ( t , conn , p . GetPublicId ())
failCases := [] struct {
2020-09-23 08:10:27 -07:00
name string
2020-10-02 16:45:32 -07:00
req * pbs . RemoveGroupMembersRequest
2020-09-23 08:10:27 -07:00
err error
2020-07-22 15:10:21 -07:00
}{
{
name : "Bad Group Id" ,
2020-10-02 16:45:32 -07:00
req : & pbs . RemoveGroupMembersRequest {
2020-07-22 15:10:21 -07:00
Id : "bad id" ,
2020-08-07 12:55:02 -04:00
Version : grp . GetVersion (),
2020-07-22 15:10:21 -07:00
},
2020-09-23 08:10:27 -07:00
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
2020-07-22 15:10:21 -07:00
},
2020-10-02 16:45:32 -07:00
{
name : "Invalid user id in member list" ,
req : & pbs . RemoveGroupMembersRequest {
2020-10-06 13:17:28 -04:00
Id : grp . GetPublicId (),
Version : grp . GetVersion (),
2020-10-02 16:45:32 -07:00
MemberIds : [] string { "invalid" },
},
err : handlers . ApiErrorWithCode ( codes . InvalidArgument ),
},
2020-07-22 15:10:21 -07:00
}
for _ , tc := range failCases {
t . Run ( tc . name , func ( t * testing . T ) {
2020-09-23 08:10:27 -07:00
assert , require := assert . New ( t ), require . New ( t )
2021-03-25 03:15:43 -04:00
_ , gErr := s . RemoveGroupMembers ( auth . DisabledAuthTestContext ( repoFn , grp . GetScopeId ()), tc . req )
2020-09-23 08:10:27 -07:00
if tc . err != nil {
require . Error ( gErr )
2020-10-02 16:45:32 -07:00
assert . True ( errors . Is ( gErr , tc . err ), "RemoveGroupMembers(%+v) got error %v, wanted %v" , tc . req , gErr , tc . err )
2020-09-23 08:10:27 -07:00
}
2020-06-15 15:22:41 -07:00
})
}
}