@@ -11,10 +11,12 @@ import (
1111 "github.com/conductorone/baton-sdk/pkg/pagination"
1212 "github.com/conductorone/baton-sdk/pkg/sdk"
1313 "github.com/google/go-github/v41/github"
14+ "github.com/shurcooL/githubv4"
15+ "google.golang.org/protobuf/types/known/timestamppb"
1416)
1517
1618// Create a new connector resource for a github user.
17- func userResource (ctx context.Context , user * github.User ) (* v2.Resource , error ) {
19+ func userResource (ctx context.Context , user * github.User , userEmail string ) (* v2.Resource , error ) {
1820 displayName := user .GetName ()
1921 if displayName == "" {
2022 // users do not always specify a name and we only get public email from
@@ -44,7 +46,7 @@ func userResource(ctx context.Context, user *github.User) (*v2.Resource, error)
4446 resourceTypeUser ,
4547 nil ,
4648 user .GetID (),
47- user . GetEmail () ,
49+ userEmail ,
4850 profile ,
4951 & v2.ExternalLink {Url : user .GetHTMLURL ()},
5052 & v2.V1Identifier {Id : strconv .FormatInt (user .GetID (), 10 )},
@@ -57,15 +59,18 @@ func userResource(ctx context.Context, user *github.User) (*v2.Resource, error)
5759}
5860
5961type userResourceType struct {
60- resourceType * v2.ResourceType
61- client * github.Client
62+ resourceType * v2.ResourceType
63+ client * github.Client
64+ graphqlClient * githubv4.Client
65+ hasSAMLEnabled * bool
6266}
6367
6468func (o * userResourceType ) ResourceType (_ context.Context ) * v2.ResourceType {
6569 return o .resourceType
6670}
6771
6872func (o * userResourceType ) List (ctx context.Context , parentID * v2.ResourceId , pt * pagination.Token ) ([]* v2.Resource , string , annotations.Annotations , error ) {
73+ var annotations annotations.Annotations
6974 if parentID == nil {
7075 return nil , "" , nil , nil
7176 }
@@ -80,6 +85,13 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
8085 return nil , "" , nil , err
8186 }
8287
88+ hasSamlBool , err := o .hasSAML (ctx , orgName )
89+ if err != nil {
90+ return nil , "" , nil , err
91+ }
92+ q := listUsersQuery {}
93+ var restApiRateLimit * v2.RateLimitDescription
94+
8395 opts := github.ListMembersOptions {
8496 ListOptions : github.ListOptions {Page : page , PerPage : pt .Size },
8597 }
@@ -89,7 +101,12 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
89101 return nil , "" , nil , fmt .Errorf ("github-connector: ListMembers failed: %w" , err )
90102 }
91103
92- nextPage , reqAnnos , err := parseResp (resp )
104+ restApiRateLimit , err = extractRateLimitData (resp )
105+ if err != nil {
106+ return nil , "" , nil , err
107+ }
108+
109+ nextPage , _ , err := parseResp (resp )
93110 if err != nil {
94111 return nil , "" , nil , err
95112 }
@@ -105,15 +122,39 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
105122 if err != nil {
106123 return nil , "" , nil , err
107124 }
108- ur , err := userResource (ctx , u )
125+ userEmail := u .GetEmail ()
126+ if hasSamlBool {
127+ q = listUsersQuery {}
128+ variables := map [string ]interface {}{
129+ "orgLoginName" : githubv4 .String (orgName ),
130+ "userName" : githubv4 .String (u .GetLogin ()),
131+ }
132+ err = o .graphqlClient .Query (ctx , & q , variables )
133+ if err != nil {
134+ return nil , "" , nil , err
135+ }
136+ if len (q .Organization .SamlIdentityProvider .ExternalIdentities .Edges ) == 1 {
137+ userEmail = q .Organization .SamlIdentityProvider .ExternalIdentities .Edges [0 ].Node .SamlIdentity .NameId
138+ }
139+ }
140+ ur , err := userResource (ctx , u , userEmail )
109141 if err != nil {
110142 return nil , "" , nil , err
111143 }
112144
113145 rv = append (rv , ur )
114146 }
147+ annotations .WithRateLimiting (restApiRateLimit )
148+ if * o .hasSAMLEnabled && int64 (q .RateLimit .Remaining ) < restApiRateLimit .Remaining {
149+ graphqlRateLimit := & v2.RateLimitDescription {
150+ Limit : int64 (q .RateLimit .Limit ),
151+ Remaining : int64 (q .RateLimit .Remaining ),
152+ ResetAt : timestamppb .New (q .RateLimit .ResetAt .Time ),
153+ }
154+ annotations .WithRateLimiting (graphqlRateLimit )
155+ }
115156
116- return rv , pageToken , reqAnnos , nil
157+ return rv , pageToken , annotations , nil
117158}
118159
119160func (o * userResourceType ) Entitlements (_ context.Context , _ * v2.Resource , _ * pagination.Token ) ([]* v2.Entitlement , string , annotations.Annotations , error ) {
@@ -124,9 +165,32 @@ func (o *userResourceType) Grants(_ context.Context, _ *v2.Resource, _ *paginati
124165 return nil , "" , nil , nil
125166}
126167
127- func userBuilder (client * github.Client ) * userResourceType {
168+ func userBuilder (client * github.Client , hasSAMLEnabled * bool , graphqlClient * githubv4. Client ) * userResourceType {
128169 return & userResourceType {
129- resourceType : resourceTypeUser ,
130- client : client ,
170+ resourceType : resourceTypeUser ,
171+ client : client ,
172+ graphqlClient : graphqlClient ,
173+ hasSAMLEnabled : hasSAMLEnabled ,
174+ }
175+ }
176+
177+ func (o * userResourceType ) hasSAML (ctx context.Context , orgName string ) (bool , error ) {
178+ if o .hasSAMLEnabled != nil {
179+ return * o .hasSAMLEnabled , nil
180+ }
181+
182+ samlBool := false
183+ q := hasSAMLQuery {}
184+ variables := map [string ]interface {}{
185+ "orgLoginName" : githubv4 .String (orgName ),
186+ }
187+ err := o .graphqlClient .Query (ctx , & q , variables )
188+ if err != nil {
189+ return false , err
190+ }
191+ if q .Organization .SamlIdentityProvider .Id != "" {
192+ samlBool = true
131193 }
194+ o .hasSAMLEnabled = & samlBool
195+ return * o .hasSAMLEnabled , nil
132196}
0 commit comments