@@ -3,6 +3,8 @@ package rule
33import (
44 "context"
55
6+ "entgo.io/ent"
7+
68 "github.com/theopenlane/iam/auth"
79 "github.com/theopenlane/iam/fgax"
810
@@ -50,57 +52,84 @@ func AllowOrgMemberRoleUpdate() privacy.OrgMembershipMutationRuleFunc {
5052 return privacy .Skip
5153 }
5254
53- id , ok := m .ID ()
54- if ! ok {
55- return privacy .Skip
56- }
55+ var ids []string
56+ var err error
5757
58- member , err := m .Client ().OrgMembership .Query ().
59- Where (orgmembership .ID (id )).
60- Select (orgmembership .FieldOrganizationID , orgmembership .FieldRole ).
61- Only (ctx )
62- if err != nil {
63- return privacy .Skipf ("unable to get org membership: %v" , err )
64- }
58+ switch {
59+ case m .Op ().Is (ent .OpUpdateOne ):
6560
66- if newRole == enums . RoleOwner || member . Role == enums . RoleOwner {
67- return privacy . Skip
68- }
61+ if id , ok := m . ID (); ok {
62+ ids = [] string { id }
63+ }
6964
70- caller , ok := auth .CallerFromContext (ctx )
71- if ! ok || caller == nil {
72- return auth .ErrNoAuthUser
65+ case m .Op ().Is (ent .OpUpdate ):
66+
67+ ids , err = m .IDs (ctx )
68+ if err != nil {
69+ return privacy .Skipf ("unable to get org membership ids: %v" , err )
70+ }
7371 }
7472
75- check := fgax.AccessCheck {
76- SubjectID : caller .SubjectID ,
77- SubjectType : caller .SubjectType (),
78- ObjectID : member .OrganizationID ,
79- Relation : InviteRelationForRole (member .Role ),
80- Context : utils .NewOrganizationContextKey (caller .SubjectEmail ),
73+ if len (ids ) == 0 {
74+ ids , err = m .IDs (ctx )
8175 }
8276
83- access , err := m .Authz .CheckOrgAccess (ctx , check )
77+ members , err := m .Client ().OrgMembership .Query ().
78+ Where (orgmembership .IDIn (ids ... )).
79+ Select (orgmembership .FieldOrganizationID , orgmembership .FieldRole ).
80+ All (ctx )
8481 if err != nil {
85- logx .FromContext (ctx ).Error ().Err (err ).Interface ("tuple" , check ).Msg ("unable to check role assignment access" )
86- return privacy .Skipf ("unable to check access: %v" , err )
82+ return privacy .Skipf ("unable to get org membership: %v" , err )
8783 }
8884
89- if ! access {
90- return generated . ErrPermissionDenied
85+ if len ( members ) == 0 {
86+ return privacy . Allow
9187 }
9288
93- newRoleAccess := check
94- newRoleAccess .Relation = InviteRelationForRole (newRole )
89+ if newRole == enums .RoleOwner {
90+ return privacy .Skip
91+ }
9592
96- access , err = m .Authz .CheckOrgAccess (ctx , newRoleAccess )
97- if err != nil {
98- logx .FromContext (ctx ).Error ().Err (err ).Interface ("tuple" , newRoleAccess ).Msg ("unable to check role assignment access" )
99- return privacy .Skipf ("unable to check access: %v" , err )
93+ caller , ok := auth .CallerFromContext (ctx )
94+ if ! ok || caller == nil {
95+ return auth .ErrNoAuthUser
10096 }
10197
102- if ! access {
103- return generated .ErrPermissionDenied
98+ for _ , member := range members {
99+ if member .Role == enums .RoleOwner {
100+ return privacy .Skip
101+ }
102+
103+ check := fgax.AccessCheck {
104+ SubjectID : caller .SubjectID ,
105+ SubjectType : caller .SubjectType (),
106+ ObjectID : member .OrganizationID ,
107+ Relation : InviteRelationForRole (member .Role ),
108+ Context : utils .NewOrganizationContextKey (caller .SubjectEmail ),
109+ }
110+
111+ access , err := m .Authz .CheckOrgAccess (ctx , check )
112+ if err != nil {
113+ logx .FromContext (ctx ).Error ().Err (err ).Interface ("tuple" , check ).Msg ("unable to check role assignment access" )
114+ return privacy .Skipf ("unable to check access: %v" , err )
115+ }
116+
117+ if ! access {
118+ return generated .ErrPermissionDenied
119+ }
120+
121+ newRoleAccess := check
122+ newRoleAccess .Relation = InviteRelationForRole (newRole )
123+
124+ access , err = m .Authz .CheckOrgAccess (ctx , newRoleAccess )
125+ if err != nil {
126+ logx .FromContext (ctx ).Error ().Err (err ).Interface ("tuple" , newRoleAccess ).Msg ("unable to check role assignment access" )
127+ return privacy .Skipf ("unable to check access: %v" , err )
128+ }
129+
130+ if ! access {
131+ return generated .ErrPermissionDenied
132+ }
104133 }
105134
106135 return privacy .Allow
0 commit comments