@@ -326,13 +326,20 @@ func TestCustomOrganizationRole(t *testing.T) {
326
326
},
327
327
})
328
328
329
- orgAdmin , _ := coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .ScopedRoleOrgAdmin (first .OrganizationID ))
329
+ orgAdmin , orgAdminUser := coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .ScopedRoleOrgAdmin (first .OrganizationID ))
330
330
ctx := testutil .Context (t , testutil .WaitMedium )
331
331
332
- //nolint:gocritic // owner is required for this
333
- createdRole , err := orgAdmin .PatchOrganizationRole (ctx , first .OrganizationID , templateAdminCustom (first .OrganizationID ))
332
+ createdRole , err := orgAdmin .PatchOrganizationRole (ctx , templateAdminCustom (first .OrganizationID ))
334
333
require .NoError (t , err , "upsert role" )
335
334
335
+ //nolint:gocritic // org_admin cannot assign to themselves
336
+ _ , err = owner .UpdateOrganizationMemberRoles (ctx , first .OrganizationID , orgAdminUser .ID .String (), codersdk.UpdateRoles {
337
+ // Give the user this custom role, to ensure when it is deleted, the user
338
+ // is ok to be used.
339
+ Roles : []string {createdRole .Name , rbac .ScopedRoleOrgAdmin (first .OrganizationID ).Name },
340
+ })
341
+ require .NoError (t , err , "assign custom role to user" )
342
+
336
343
existingRoles , err := orgAdmin .ListOrganizationRoles (ctx , first .OrganizationID )
337
344
require .NoError (t , err )
338
345
@@ -352,6 +359,75 @@ func TestCustomOrganizationRole(t *testing.T) {
352
359
return role .Name == createdRole .Name
353
360
})
354
361
require .False (t , exists , "custom role should be deleted" )
362
+
363
+ // Verify you can still assign roles.
364
+ // There used to be a bug that if a member had a delete role, they
365
+ // could not be assigned roles anymore.
366
+ //nolint:gocritic // org_admin cannot assign to themselves
367
+ _ , err = owner .UpdateOrganizationMemberRoles (ctx , first .OrganizationID , orgAdminUser .ID .String (), codersdk.UpdateRoles {
368
+ Roles : []string {rbac .ScopedRoleOrgAdmin (first .OrganizationID ).Name },
369
+ })
370
+ require .NoError (t , err )
371
+ })
372
+
373
+ // Verify deleting a custom role cascades to all members
374
+ t .Run ("DeleteRoleCascadeMembers" , func (t * testing.T ) {
375
+ t .Parallel ()
376
+ dv := coderdtest .DeploymentValues (t )
377
+ dv .Experiments = []string {string (codersdk .ExperimentCustomRoles )}
378
+ owner , first := coderdenttest .New (t , & coderdenttest.Options {
379
+ Options : & coderdtest.Options {
380
+ DeploymentValues : dv ,
381
+ },
382
+ LicenseOptions : & coderdenttest.LicenseOptions {
383
+ Features : license.Features {
384
+ codersdk .FeatureCustomRoles : 1 ,
385
+ },
386
+ },
387
+ })
388
+
389
+ orgAdmin , orgAdminUser := coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .ScopedRoleOrgAdmin (first .OrganizationID ))
390
+ ctx := testutil .Context (t , testutil .WaitMedium )
391
+
392
+ createdRole , err := orgAdmin .PatchOrganizationRole (ctx , templateAdminCustom (first .OrganizationID ))
393
+ require .NoError (t , err , "upsert role" )
394
+
395
+ customRoleIdentifier := rbac.RoleIdentifier {
396
+ Name : createdRole .Name ,
397
+ OrganizationID : first .OrganizationID ,
398
+ }
399
+
400
+ // Create a few members with the role
401
+ coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , customRoleIdentifier )
402
+ coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .ScopedRoleOrgAdmin (first .OrganizationID ), customRoleIdentifier )
403
+ coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .ScopedRoleOrgTemplateAdmin (first .OrganizationID ), rbac .ScopedRoleOrgAuditor (first .OrganizationID ), customRoleIdentifier )
404
+
405
+ // Verify members have the custom role
406
+ members , err := orgAdmin .OrganizationMembers (ctx , first .OrganizationID )
407
+ require .NoError (t , err )
408
+ require .Len (t , members , 5 ) // 3 members + org admin + owner
409
+ for _ , member := range members {
410
+ if member .UserID == orgAdminUser .ID || member .UserID == first .UserID {
411
+ continue
412
+ }
413
+
414
+ require .True (t , slices .ContainsFunc (member .Roles , func (role codersdk.SlimRole ) bool {
415
+ return role .Name == customRoleIdentifier .Name
416
+ }), "member should have custom role" )
417
+ }
418
+
419
+ err = orgAdmin .DeleteOrganizationRole (ctx , first .OrganizationID , createdRole .Name )
420
+ require .NoError (t , err )
421
+
422
+ // Verify the role was removed from all members
423
+ members , err = orgAdmin .OrganizationMembers (ctx , first .OrganizationID )
424
+ require .NoError (t , err )
425
+ require .Len (t , members , 5 ) // 3 members + org admin + owner
426
+ for _ , member := range members {
427
+ require .False (t , slices .ContainsFunc (member .Roles , func (role codersdk.SlimRole ) bool {
428
+ return role .Name == customRoleIdentifier .Name
429
+ }), "role should be removed from all users" )
430
+ }
355
431
})
356
432
}
357
433
0 commit comments