@@ -162,7 +162,7 @@ var (
162
162
ID : uuid .Nil .String (),
163
163
Roles : rbac .Roles ([]rbac.Role {
164
164
{
165
- Name : "provisionerd" ,
165
+ Name : rbac. RoleName { Name : "provisionerd" } ,
166
166
DisplayName : "Provisioner Daemon" ,
167
167
Site : rbac .Permissions (map [string ][]policy.Action {
168
168
// TODO: Add ProvisionerJob resource type.
@@ -191,7 +191,7 @@ var (
191
191
ID : uuid .Nil .String (),
192
192
Roles : rbac .Roles ([]rbac.Role {
193
193
{
194
- Name : "autostart" ,
194
+ Name : rbac. RoleName { Name : "autostart" } ,
195
195
DisplayName : "Autostart Daemon" ,
196
196
Site : rbac .Permissions (map [string ][]policy.Action {
197
197
rbac .ResourceSystem .Type : {policy .WildcardSymbol },
@@ -213,7 +213,7 @@ var (
213
213
ID : uuid .Nil .String (),
214
214
Roles : rbac .Roles ([]rbac.Role {
215
215
{
216
- Name : "hangdetector" ,
216
+ Name : rbac. RoleName { Name : "hangdetector" } ,
217
217
DisplayName : "Hang Detector Daemon" ,
218
218
Site : rbac .Permissions (map [string ][]policy.Action {
219
219
rbac .ResourceSystem .Type : {policy .WildcardSymbol },
@@ -232,7 +232,7 @@ var (
232
232
ID : uuid .Nil .String (),
233
233
Roles : rbac .Roles ([]rbac.Role {
234
234
{
235
- Name : "system" ,
235
+ Name : rbac. RoleName { Name : "system" } ,
236
236
DisplayName : "Coder" ,
237
237
Site : rbac .Permissions (map [string ][]policy.Action {
238
238
rbac .ResourceWildcard .Type : {policy .ActionRead },
@@ -582,24 +582,33 @@ func (q *querier) authorizeUpdateFileTemplate(ctx context.Context, file database
582
582
}
583
583
}
584
584
585
- // uniqueOrganizationRoles converts a set of scoped role names to their unique
585
+ // convertToOrganizationRoles converts a set of scoped role names to their unique
586
586
// scoped names.
587
- func (q * querier ) uniqueOrganizationRoles (organizationID uuid.UUID , names []string ) ([]rbac.RoleName , error ) {
587
+ func (q * querier ) convertToOrganizationRoles (organizationID uuid.UUID , names []string ) ([]rbac.RoleName , error ) {
588
588
uniques := make ([]rbac.RoleName , 0 , len (names ))
589
589
for _ , name := range names {
590
590
// This check is a developer safety check. Old code might try to invoke this code path with
591
591
// organization id suffixes. Catch this and return a nice error so it can be fixed.
592
- _ , foundOrg , _ := rbac .RoleSplit (rbac .RoleName (name ))
593
- if foundOrg != "" {
592
+ if strings .Contains (name , ":" ) {
594
593
return nil , xerrors .Errorf ("attempt to assign a role %q, remove the ':<organization_id> suffix" , name )
595
594
}
596
595
597
- uniques = append (uniques , rbac .RoleName ( name , organizationID . String ()) )
596
+ uniques = append (uniques , rbac.RoleName { Name : name , OrganizationID : organizationID } )
598
597
}
599
598
600
599
return uniques , nil
601
600
}
602
601
602
+ // convertToDeploymentRoles converts string role names into deployment wide roles.
603
+ func (q * querier ) convertToDeploymentRoles (names []string ) []rbac.RoleName {
604
+ uniques := make ([]rbac.RoleName , 0 , len (names ))
605
+ for _ , name := range names {
606
+ uniques = append (uniques , rbac.RoleName {Name : name })
607
+ }
608
+
609
+ return uniques
610
+ }
611
+
603
612
// canAssignRoles handles assigning built in and custom roles.
604
613
func (q * querier ) canAssignRoles (ctx context.Context , orgID * uuid.UUID , added , removed []rbac.RoleName ) error {
605
614
actor , ok := ActorFromContext (ctx )
@@ -618,25 +627,21 @@ func (q *querier) canAssignRoles(ctx context.Context, orgID *uuid.UUID, added, r
618
627
customRoles := make ([]rbac.RoleName , 0 )
619
628
// Validate that the roles being assigned are valid.
620
629
for _ , r := range grantedRoles {
621
- roleOrgIDStr , isOrgRole := rbac . IsOrgRole ( r )
630
+ isOrgRole := r . OrganizationID != uuid . Nil
622
631
if shouldBeOrgRoles && ! isOrgRole {
623
632
return xerrors .Errorf ("Must only update org roles" )
624
633
}
634
+
625
635
if ! shouldBeOrgRoles && isOrgRole {
626
636
return xerrors .Errorf ("Must only update site wide roles" )
627
637
}
628
638
629
639
if shouldBeOrgRoles {
630
- roleOrgID , err := uuid .Parse (roleOrgIDStr )
631
- if err != nil {
632
- return xerrors .Errorf ("role %q has invalid uuid for org: %w" , r , err )
633
- }
634
-
635
640
if orgID == nil {
636
641
return xerrors .Errorf ("should never happen, orgID is nil, but trying to assign an organization role" )
637
642
}
638
643
639
- if roleOrgID != * orgID {
644
+ if r . OrganizationID != * orgID {
640
645
return xerrors .Errorf ("attempted to assign role from a different org, role %q to %q" , r , orgID .String ())
641
646
}
642
647
}
@@ -667,7 +672,7 @@ func (q *querier) canAssignRoles(ctx context.Context, orgID *uuid.UUID, added, r
667
672
// returns them all, but then someone could pass in a large list to make us do
668
673
// a lot of loop iterations.
669
674
if ! slices .ContainsFunc (expandedCustomRoles , func (customRole rbac.Role ) bool {
670
- return strings .EqualFold (customRole .Name , role )
675
+ return strings .EqualFold (customRole .Name . Name , role . Name ) && customRole . Name . OrganizationID == role . OrganizationID
671
676
}) {
672
677
return xerrors .Errorf ("%q is not a supported role" , role )
673
678
}
@@ -2489,9 +2494,14 @@ func (q *querier) InsertOrganization(ctx context.Context, arg database.InsertOrg
2489
2494
}
2490
2495
2491
2496
func (q * querier ) InsertOrganizationMember (ctx context.Context , arg database.InsertOrganizationMemberParams ) (database.OrganizationMember , error ) {
2497
+ orgRoles , err := q .convertToOrganizationRoles (arg .OrganizationID , arg .Roles )
2498
+ if err != nil {
2499
+ return database.OrganizationMember {}, xerrors .Errorf ("converting to organization roles: %w" , err )
2500
+ }
2501
+
2492
2502
// All roles are added roles. Org member is always implied.
2493
- addedRoles := append (arg . Roles , rbac .ScopedRoleOrgMember (arg .OrganizationID ))
2494
- err : = q .canAssignRoles (ctx , & arg .OrganizationID , addedRoles , []string {})
2503
+ addedRoles := append (orgRoles , rbac .ScopedRoleOrgMember (arg .OrganizationID ))
2504
+ err = q .canAssignRoles (ctx , & arg .OrganizationID , addedRoles , []rbac. RoleName {})
2495
2505
if err != nil {
2496
2506
return database.OrganizationMember {}, err
2497
2507
}
@@ -2577,8 +2587,8 @@ func (q *querier) InsertTemplateVersionWorkspaceTag(ctx context.Context, arg dat
2577
2587
2578
2588
func (q * querier ) InsertUser (ctx context.Context , arg database.InsertUserParams ) (database.User , error ) {
2579
2589
// Always check if the assigned roles can actually be assigned by this actor.
2580
- impliedRoles := append ([]string {rbac .RoleMember ()}, arg .RBACRoles ... )
2581
- err := q .canAssignRoles (ctx , nil , impliedRoles , []string {})
2590
+ impliedRoles := append ([]rbac. RoleName {rbac .RoleMember ()}, q . convertToDeploymentRoles ( arg .RBACRoles ) ... )
2591
+ err := q .canAssignRoles (ctx , nil , impliedRoles , []rbac. RoleName {})
2582
2592
if err != nil {
2583
2593
return database.User {}, err
2584
2594
}
@@ -2865,23 +2875,22 @@ func (q *querier) UpdateMemberRoles(ctx context.Context, arg database.UpdateMemb
2865
2875
return database.OrganizationMember {}, err
2866
2876
}
2867
2877
2878
+ originalRoles , err := q .convertToOrganizationRoles (member .OrganizationID , member .Roles )
2879
+ if err != nil {
2880
+ return database.OrganizationMember {}, xerrors .Errorf ("convert original roles: %w" , err )
2881
+ }
2882
+
2868
2883
// The 'rbac' package expects role names to be scoped.
2869
2884
// Convert the argument roles for validation.
2870
- scopedGranted := make ([]rbac.RoleName , 0 , len (arg .GrantedRoles ))
2871
- for _ , grantedRole := range arg .GrantedRoles {
2872
- // This check is a developer safety check. Old code might try to invoke this code path with
2873
- // organization id suffixes. Catch this and return a nice error so it can be fixed.
2874
- _ , foundOrg , _ := rbac .RoleSplit (grantedRole )
2875
- if foundOrg != "" {
2876
- return database.OrganizationMember {}, xerrors .Errorf ("attempt to assign a role %q, remove the ':<organization_id> suffix" , grantedRole )
2877
- }
2878
-
2879
- scopedGranted = append (scopedGranted , rbac .RoleName (grantedRole , arg .OrgID .String ()))
2885
+ scopedGranted , err := q .convertToOrganizationRoles (arg .OrgID , arg .GrantedRoles )
2886
+ if err != nil {
2887
+ return database.OrganizationMember {}, err
2880
2888
}
2881
2889
2882
2890
// The org member role is always implied.
2883
2891
impliedTypes := append (scopedGranted , rbac .ScopedRoleOrgMember (arg .OrgID ))
2884
- added , removed := rbac .ChangeRoleSet (member .Roles , impliedTypes )
2892
+
2893
+ added , removed := rbac .ChangeRoleSet (originalRoles , impliedTypes )
2885
2894
err = q .canAssignRoles (ctx , & arg .OrgID , added , removed )
2886
2895
if err != nil {
2887
2896
return database.OrganizationMember {}, err
@@ -3222,9 +3231,9 @@ func (q *querier) UpdateUserRoles(ctx context.Context, arg database.UpdateUserRo
3222
3231
}
3223
3232
3224
3233
// The member role is always implied.
3225
- impliedTypes := append (arg .GrantedRoles , rbac .RoleMember ())
3234
+ impliedTypes := append (q . convertToDeploymentRoles ( arg .GrantedRoles ) , rbac .RoleMember ())
3226
3235
// If the changeset is nothing, less rbac checks need to be done.
3227
- added , removed := rbac .ChangeRoleSet (user .RBACRoles , impliedTypes )
3236
+ added , removed := rbac .ChangeRoleSet (q . convertToDeploymentRoles ( user .RBACRoles ) , impliedTypes )
3228
3237
err = q .canAssignRoles (ctx , nil , added , removed )
3229
3238
if err != nil {
3230
3239
return database.User {}, err
0 commit comments