Skip to content

Commit 86c4ec1

Browse files
committed
emitting org role entitlements and grant counts
1 parent 1f108ab commit 86c4ec1

File tree

1 file changed

+109
-1
lines changed

1 file changed

+109
-1
lines changed

pkg/connector/team.go

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package connector
33
import (
44
"context"
55
"fmt"
6+
"net/http"
67
"strconv"
78
"strings"
89

@@ -128,8 +129,10 @@ func (o *teamResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
128129
return rv, pageToken, reqAnnos, nil
129130
}
130131

131-
func (o *teamResourceType) Entitlements(_ context.Context, resource *v2.Resource, _ *pagination.Token) ([]*v2.Entitlement, string, annotations.Annotations, error) {
132+
func (o *teamResourceType) Entitlements(ctx context.Context, resource *v2.Resource, _ *pagination.Token) ([]*v2.Entitlement, string, annotations.Annotations, error) {
132133
rv := make([]*v2.Entitlement, 0, len(teamAccessLevels))
134+
135+
// Add team role entitlements
133136
for _, level := range teamAccessLevels {
134137
rv = append(
135138
rv,
@@ -148,6 +151,60 @@ func (o *teamResourceType) Entitlements(_ context.Context, resource *v2.Resource
148151
)
149152
}
150153

154+
// Get organization roles for this team
155+
orgName, err := o.orgCache.GetOrgName(ctx, resource.ParentResourceId)
156+
if err != nil {
157+
return rv, "", nil, nil // Return what we have so far if we can't get org name
158+
}
159+
160+
roles, resp, err := o.client.Organizations.ListRoles(ctx, orgName)
161+
if err != nil {
162+
// Handle permission errors gracefully
163+
if resp != nil && (resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusNotFound) {
164+
return rv, "", nil, nil // Return what we have so far if we don't have permission
165+
}
166+
return rv, "", nil, nil // Return what we have so far if request failed
167+
}
168+
169+
// Get team ID for checking role assignments
170+
teamID, err := strconv.ParseInt(resource.Id.Resource, 10, 64)
171+
if err != nil {
172+
return rv, "", nil, nil // Return what we have so far if we can't parse team ID
173+
}
174+
175+
// Add organization role entitlements only for roles the team is assigned to
176+
for _, role := range roles.CustomRepoRoles {
177+
// Check if team is assigned to this role
178+
teams, resp, err := o.client.Organizations.ListTeamsAssignedToOrgRole(ctx, orgName, role.GetID(), nil)
179+
if err != nil {
180+
// Skip this role if we can't check assignments
181+
if resp != nil && (resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusNotFound) {
182+
continue
183+
}
184+
continue
185+
}
186+
187+
// Check if this team is in the list of teams with this role
188+
for _, team := range teams {
189+
if team.GetID() == teamID {
190+
rv = append(
191+
rv,
192+
entitlement.NewAssignmentEntitlement(
193+
resource,
194+
role.GetName(),
195+
entitlement.WithDisplayName(role.GetName()),
196+
entitlement.WithDescription(role.GetDescription()),
197+
entitlement.WithAnnotation(&v2.V1Identifier{
198+
Id: fmt.Sprintf("team:%s:org_role:%d", resource.Id.Resource, role.GetID()),
199+
}),
200+
entitlement.WithGrantableTo(resourceTypeUser),
201+
),
202+
)
203+
break // Found the team, no need to check other teams
204+
}
205+
}
206+
}
207+
151208
return rv, "", nil, nil
152209
}
153210

@@ -221,6 +278,57 @@ func (o *teamResourceType) Grants(ctx context.Context, resource *v2.Resource, pT
221278
))
222279
}
223280

281+
// Get organization roles for this team
282+
orgName, err := o.orgCache.GetOrgName(ctx, resource.ParentResourceId)
283+
if err != nil {
284+
return rv, pageToken, reqAnnos, nil // Return what we have so far if we can't get org name
285+
}
286+
287+
roles, resp, err := o.client.Organizations.ListRoles(ctx, orgName)
288+
if err != nil {
289+
// Handle permission errors gracefully
290+
if resp != nil && (resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusNotFound) {
291+
return rv, pageToken, reqAnnos, nil // Return what we have so far if we don't have permission
292+
}
293+
return rv, pageToken, reqAnnos, nil // Return what we have so far if request failed
294+
}
295+
296+
// Add grants for organization roles
297+
for _, role := range roles.CustomRepoRoles {
298+
// Check if team is assigned to this role
299+
teams, resp, err := o.client.Organizations.ListTeamsAssignedToOrgRole(ctx, orgName, role.GetID(), nil)
300+
if err != nil {
301+
// Skip this role if we can't check assignments
302+
if resp != nil && (resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusNotFound) {
303+
continue
304+
}
305+
continue
306+
}
307+
308+
// Check if this team is in the list of teams with this role
309+
for _, team := range teams {
310+
if team.GetID() == githubID {
311+
// Create a grant for each team member with this role
312+
for _, user := range users {
313+
ur, err := userResource(ctx, user, user.GetEmail(), nil)
314+
if err != nil {
315+
continue
316+
}
317+
318+
rv = append(rv, grant.NewGrant(
319+
resource,
320+
role.GetName(),
321+
ur.Id,
322+
grant.WithAnnotation(&v2.V1Identifier{
323+
Id: fmt.Sprintf("team-org-role-grant:%s:%d:%s", resource.Id.Resource, user.GetID(), role.GetName()),
324+
}),
325+
))
326+
}
327+
break // Found the team, no need to check other teams
328+
}
329+
}
330+
}
331+
224332
return rv, pageToken, reqAnnos, nil
225333
}
226334

0 commit comments

Comments
 (0)