@@ -85,7 +85,7 @@ func TestGroupSyncTable(t *testing.T) {
8585testCases := []orgSetupDefinition {
8686{
8787Name :"SwitchGroups" ,
88- Settings :& codersdk.GroupSyncSettings {
88+ GroupSettings :& codersdk.GroupSyncSettings {
8989Field :"groups" ,
9090Mapping :map [string ][]uuid.UUID {
9191"foo" : {ids .ID ("sg-foo" ),ids .ID ("sg-foo-2" )},
@@ -102,16 +102,18 @@ func TestGroupSyncTable(t *testing.T) {
102102ids .ID ("sg-bar" ):false ,
103103ids .ID ("sg-baz" ):false ,
104104},
105- ExpectedGroups : []uuid.UUID {
106- ids .ID ("sg-foo" ),
107- ids .ID ("sg-foo-2" ),
108- ids .ID ("sg-bar" ),
109- ids .ID ("sg-baz" ),
105+ assertGroups :& orgGroupAssert {
106+ ExpectedGroups : []uuid.UUID {
107+ ids .ID ("sg-foo" ),
108+ ids .ID ("sg-foo-2" ),
109+ ids .ID ("sg-bar" ),
110+ ids .ID ("sg-baz" ),
111+ },
110112},
111113},
112114{
113115Name :"StayInGroup" ,
114- Settings :& codersdk.GroupSyncSettings {
116+ GroupSettings :& codersdk.GroupSyncSettings {
115117Field :"groups" ,
116118// Only match foo, so bar does not map
117119RegexFilter :regexp .MustCompile ("^foo$" ),
@@ -125,13 +127,15 @@ func TestGroupSyncTable(t *testing.T) {
125127ids .ID ("gg-foo" ):true ,
126128ids .ID ("gg-bar" ):false ,
127129},
128- ExpectedGroups : []uuid.UUID {
129- ids .ID ("gg-foo" ),
130+ assertGroups :& orgGroupAssert {
131+ ExpectedGroups : []uuid.UUID {
132+ ids .ID ("gg-foo" ),
133+ },
130134},
131135},
132136{
133137Name :"UserJoinsGroups" ,
134- Settings :& codersdk.GroupSyncSettings {
138+ GroupSettings :& codersdk.GroupSyncSettings {
135139Field :"groups" ,
136140Mapping :map [string ][]uuid.UUID {
137141"foo" : {ids .ID ("ng-foo" ),uuid .New ()},
@@ -145,29 +149,33 @@ func TestGroupSyncTable(t *testing.T) {
145149ids .ID ("ng-bar-2" ):false ,
146150ids .ID ("ng-baz" ):false ,
147151},
148- ExpectedGroups : []uuid.UUID {
149- ids .ID ("ng-foo" ),
150- ids .ID ("ng-bar" ),
151- ids .ID ("ng-bar-2" ),
152- ids .ID ("ng-baz" ),
152+ assertGroups :& orgGroupAssert {
153+ ExpectedGroups : []uuid.UUID {
154+ ids .ID ("ng-foo" ),
155+ ids .ID ("ng-bar" ),
156+ ids .ID ("ng-bar-2" ),
157+ ids .ID ("ng-baz" ),
158+ },
153159},
154160},
155161{
156162Name :"CreateGroups" ,
157- Settings :& codersdk.GroupSyncSettings {
163+ GroupSettings :& codersdk.GroupSyncSettings {
158164Field :"groups" ,
159165RegexFilter :regexp .MustCompile ("^create" ),
160166AutoCreateMissing :true ,
161167},
162168Groups :map [uuid.UUID ]bool {},
163- ExpectedGroupNames : []string {
164- "create-bar" ,
165- "create-baz" ,
169+ assertGroups :& orgGroupAssert {
170+ ExpectedGroupNames : []string {
171+ "create-bar" ,
172+ "create-baz" ,
173+ },
166174},
167175},
168176{
169177Name :"GroupNamesNoMapping" ,
170- Settings :& codersdk.GroupSyncSettings {
178+ GroupSettings :& codersdk.GroupSyncSettings {
171179Field :"groups" ,
172180RegexFilter :regexp .MustCompile (".*" ),
173181AutoCreateMissing :false ,
@@ -177,14 +185,16 @@ func TestGroupSyncTable(t *testing.T) {
177185"bar" :false ,
178186"goob" :true ,
179187},
180- ExpectedGroupNames : []string {
181- "foo" ,
182- "bar" ,
188+ assertGroups :& orgGroupAssert {
189+ ExpectedGroupNames : []string {
190+ "foo" ,
191+ "bar" ,
192+ },
183193},
184194},
185195{
186196Name :"NoUser" ,
187- Settings :& codersdk.GroupSyncSettings {
197+ GroupSettings :& codersdk.GroupSyncSettings {
188198Field :"groups" ,
189199Mapping :map [string ][]uuid.UUID {
190200// Extra ID that does not map to a group
@@ -200,13 +210,16 @@ func TestGroupSyncTable(t *testing.T) {
200210},
201211},
202212{
203- Name :"NoSettingsNoUser" ,
204- Settings :nil ,
205- Groups :map [uuid.UUID ]bool {},
213+ Name :"NoSettings" ,
214+ GroupSettings :nil ,
215+ Groups :map [uuid.UUID ]bool {},
216+ assertGroups :& orgGroupAssert {
217+ ExpectedGroups : []uuid.UUID {},
218+ },
206219},
207220{
208221Name :"LegacyMapping" ,
209- Settings :& codersdk.GroupSyncSettings {
222+ GroupSettings :& codersdk.GroupSyncSettings {
210223Field :"groups" ,
211224RegexFilter :regexp .MustCompile ("^legacy" ),
212225LegacyNameMapping :map [string ]string {
@@ -224,9 +237,11 @@ func TestGroupSyncTable(t *testing.T) {
224237"extra" :true ,
225238"legacy-bop" :true ,
226239},
227- ExpectedGroupNames : []string {
228- "legacy-bar" ,
229- "legacy-foo" ,
240+ assertGroups :& orgGroupAssert {
241+ ExpectedGroupNames : []string {
242+ "legacy-bar" ,
243+ "legacy-foo" ,
244+ },
230245},
231246},
232247}
@@ -311,9 +326,10 @@ func TestGroupSyncTable(t *testing.T) {
311326"random" :true ,
312327},
313328// No settings, because they come from the deployment values
314- Settings :nil ,
315- ExpectedGroups :nil ,
316- ExpectedGroupNames : []string {"legacy-foo" ,"legacy-baz" ,"legacy-bar" },
329+ GroupSettings :nil ,
330+ assertGroups :& orgGroupAssert {
331+ ExpectedGroupNames : []string {"legacy-foo" ,"legacy-baz" ,"legacy-bar" },
332+ },
317333}
318334
319335//nolint:gocritic // testing
@@ -385,16 +401,18 @@ func TestSyncDisabled(t *testing.T) {
385401ids .ID ("baz" ):false ,
386402ids .ID ("bop" ):false ,
387403},
388- Settings :& codersdk.GroupSyncSettings {
404+ GroupSettings :& codersdk.GroupSyncSettings {
389405Field :"groups" ,
390406Mapping :map [string ][]uuid.UUID {
391407"foo" : {ids .ID ("foo" )},
392408"baz" : {ids .ID ("baz" )},
393409},
394410},
395- ExpectedGroups : []uuid.UUID {
396- ids .ID ("foo" ),
397- ids .ID ("bar" ),
411+ assertGroups :& orgGroupAssert {
412+ ExpectedGroups : []uuid.UUID {
413+ ids .ID ("foo" ),
414+ ids .ID ("bar" ),
415+ },
398416},
399417}
400418
@@ -728,9 +746,14 @@ func SetupOrganization(t *testing.T, s *idpsync.AGPLIDPSync, db database.Store,
728746}
729747
730748manager := runtimeconfig .NewManager ()
731- if def .Settings != nil {
732- orgResolver := manager .OrganizationResolver (db ,org .ID )
733- err = s .Group .SetRuntimeValue (context .Background (),orgResolver , (* idpsync .GroupSyncSettings )(def .Settings ))
749+ orgResolver := manager .OrganizationResolver (db ,org .ID )
750+ if def .GroupSettings != nil {
751+ err = s .Group .SetRuntimeValue (context .Background (),orgResolver , (* idpsync .GroupSyncSettings )(def .GroupSettings ))
752+ require .NoError (t ,err )
753+ }
754+
755+ if def .RoleSettings != nil {
756+ err = s .Role .SetRuntimeValue (context .Background (),orgResolver ,def .RoleSettings )
734757require .NoError (t ,err )
735758}
736759
@@ -740,6 +763,33 @@ func SetupOrganization(t *testing.T, s *idpsync.AGPLIDPSync, db database.Store,
740763OrganizationID :org .ID ,
741764})
742765}
766+
767+ if len (def .OrganizationRoles )> 0 {
768+ _ ,err := db .UpdateMemberRoles (context .Background (), database.UpdateMemberRolesParams {
769+ GrantedRoles :def .OrganizationRoles ,
770+ UserID :user .ID ,
771+ OrgID :org .ID ,
772+ })
773+ require .NoError (t ,err )
774+ }
775+
776+ if len (def .CustomRoles )> 0 {
777+ for _ ,cr := range def .CustomRoles {
778+ _ ,err := db .InsertCustomRole (context .Background (), database.InsertCustomRoleParams {
779+ Name :cr ,
780+ DisplayName :cr ,
781+ OrganizationID : uuid.NullUUID {
782+ UUID :org .ID ,
783+ Valid :true ,
784+ },
785+ SitePermissions :nil ,
786+ OrgPermissions :nil ,
787+ UserPermissions :nil ,
788+ })
789+ require .NoError (t ,err )
790+ }
791+ }
792+
743793for groupID ,in := range def .Groups {
744794dbgen .Group (t ,db , database.Group {
745795ID :groupID ,
@@ -769,11 +819,25 @@ func SetupOrganization(t *testing.T, s *idpsync.AGPLIDPSync, db database.Store,
769819type orgSetupDefinition struct {
770820Name string
771821// True if the user is a member of the group
772- Groups map [uuid.UUID ]bool
773- GroupNames map [string ]bool
774- NotMember bool
822+ Groups map [uuid.UUID ]bool
823+ GroupNames map [string ]bool
824+ OrganizationRoles []string
825+ CustomRoles []string
826+ // NotMember if true will ensure the user is not a member of the organization.
827+ NotMember bool
828+
829+ GroupSettings * codersdk.GroupSyncSettings
830+ RoleSettings * idpsync.RoleSyncSettings
831+
832+ assertGroups * orgGroupAssert
833+ assertRoles * orgRoleAssert
834+ }
835+
836+ type orgRoleAssert struct {
837+ ExpectedOrgRoles []string
838+ }
775839
776- Settings * codersdk. GroupSyncSettings
840+ type orgGroupAssert struct {
777841ExpectedGroups []uuid.UUID
778842ExpectedGroupNames []string
779843}
@@ -794,6 +858,25 @@ func (o orgSetupDefinition) Assert(t *testing.T, orgID uuid.UUID, db database.St
794858require .Len (t ,members ,1 ,"should be a member" )
795859}
796860
861+ if o .assertGroups != nil {
862+ o .assertGroups .Assert (t ,orgID ,db ,user )
863+ }
864+ if o .assertRoles != nil {
865+ o .assertRoles .Assert (t ,orgID ,db ,o .NotMember ,user )
866+ }
867+
868+ // If the user is not a member, there is nothing to really assert in the org
869+ if o .assertGroups == nil && o .assertRoles == nil && ! o .NotMember {
870+ t .Errorf ("no group or role asserts present, must have at least one" )
871+ t .FailNow ()
872+ }
873+ }
874+
875+ func (o orgGroupAssert )Assert (t * testing.T ,orgID uuid.UUID ,db database.Store ,user database.User ) {
876+ t .Helper ()
877+
878+ ctx := context .Background ()
879+
797880userGroups ,err := db .GetGroups (ctx , database.GetGroupsParams {
798881OrganizationID :orgID ,
799882HasMemberID :user .ID ,
@@ -826,3 +909,23 @@ func (o orgSetupDefinition) Assert(t *testing.T, orgID uuid.UUID, db database.St
826909require .Len (t ,o .ExpectedGroupNames ,0 ,"ExpectedGroupNames should be empty" )
827910}
828911}
912+
913+ //nolint:revive
914+ func (o orgRoleAssert )Assert (t * testing.T ,orgID uuid.UUID ,db database.Store ,notMember bool ,user database.User ) {
915+ t .Helper ()
916+
917+ ctx := context .Background ()
918+
919+ members ,err := db .OrganizationMembers (ctx , database.OrganizationMembersParams {
920+ OrganizationID :orgID ,
921+ UserID :user .ID ,
922+ })
923+ if notMember {
924+ require .ErrorIs (t ,err ,sql .ErrNoRows )
925+ return
926+ }
927+ require .NoError (t ,err )
928+ require .Len (t ,members ,1 )
929+ member := members [0 ]
930+ require .ElementsMatch (t ,member .OrganizationMember .Roles ,o .ExpectedOrgRoles )
931+ }