@@ -2,13 +2,15 @@ package connector
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67 "strings"
78
89 "github.com/conductorone/baton-jumpcloud/pkg/jcapi1"
910 v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
1011 "github.com/conductorone/baton-sdk/pkg/annotations"
1112 "github.com/conductorone/baton-sdk/pkg/pagination"
13+ sdkResources "github.com/conductorone/baton-sdk/pkg/types/resource"
1214 "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
1315 "go.uber.org/zap"
1416 "google.golang.org/protobuf/types/known/structpb"
@@ -19,18 +21,20 @@ type userResourceType struct {
1921 client1 jc1Func
2022 client2 jc2Func
2123 managers map [string ]* jcapi1.Systemuserreturn
24+ ext * ExtensionClient
2225}
2326
2427func (o * userResourceType ) ResourceType (_ context.Context ) * v2.ResourceType {
2528 return o .resourceType
2629}
2730
28- func newUserBuilder (jc1 jc1Func , jc2 jc2Func ) * userResourceType {
31+ func newUserBuilder (jc1 jc1Func , jc2 jc2Func , ext * ExtensionClient ) * userResourceType {
2932 return & userResourceType {
3033 resourceType : resourceTypeUser ,
3134 client1 : jc1 ,
3235 client2 : jc2 ,
3336 managers : make (map [string ]* jcapi1.Systemuserreturn ),
37+ ext : ext ,
3438 }
3539}
3640
@@ -43,34 +47,118 @@ func (o *userResourceType) Grants(_ context.Context, _ *v2.Resource, _ *paginati
4347}
4448
4549func (o * userResourceType ) List (ctx context.Context , parentResourceID * v2.ResourceId , pt * pagination.Token ) ([]* v2.Resource , string , annotations.Annotations , error ) {
50+ l := ctxzap .Extract (ctx )
51+
4652 ctx , client := o .client1 (ctx )
4753
4854 skip , b , err := unmarshalSkipToken (pt )
4955 if err != nil {
5056 return nil , "" , nil , err
5157 }
5258
53- list , resp , err := client .SystemusersApi .SystemusersList (ctx ).Skip (skip ).Execute ()
54- if err != nil {
55- return nil , "" , nil , err
59+ if b .Current () == nil {
60+ // Push onto stack in reverse
61+ b .Push (pagination.PageState {
62+ ResourceTypeID : "list-admin-users" ,
63+ })
64+ b .Push (pagination.PageState {
65+ ResourceTypeID : "list-users" ,
66+ })
5667 }
57- defer resp .Body .Close ()
58-
5968 var rv []* v2.Resource
60- for i := range list .Results {
61- ur , err := o .userResource (ctx , & list .Results [i ])
69+ var pageToken string
70+ switch b .Current ().ResourceTypeID {
71+ case "list-users" :
72+ list , resp , err := client .SystemusersApi .SystemusersList (ctx ).Skip (skip ).Execute ()
73+ if err != nil {
74+ return nil , "" , nil , err
75+ }
76+ defer resp .Body .Close ()
77+
78+ for i := range list .Results {
79+ ur , err := o .userResource (ctx , & list .Results [i ])
80+ if err != nil {
81+ return nil , "" , nil , err
82+ }
83+ rv = append (rv , ur )
84+ }
85+ pageToken , err = marshalSkipToken (len (list .Results ), skip , b )
86+ if err != nil {
87+ return nil , "" , nil , err
88+ }
89+ case "list-admin-users" :
90+ adminUsers , resp , err := o .ext .UserList ().Skip (skip ).Execute (ctx )
6291 if err != nil {
6392 return nil , "" , nil , err
6493 }
65- rv = append (rv , ur )
94+ defer resp .Body .Close ()
95+
96+ for i := range adminUsers {
97+ adminEmail := adminUsers [i ].GetEmail ()
98+ adminUser , err := o .adminUserResource (ctx , & adminUsers [i ])
99+ if err != nil {
100+ return nil , "" , nil , err
101+ }
102+
103+ // Check if the admin user is also a system user, if so we'll use that user instead
104+ systemUser , err := fetchUserByEmail (ctx , client , adminEmail )
105+ if err != nil && ! errors .Is (err , errUserNotFoundForEmail ) {
106+ return nil , "" , nil , err
107+ }
108+
109+ if systemUser != nil {
110+ continue
111+ }
112+
113+ l .Debug ("admin user not found as system user, creating" , zap .String ("email" , adminEmail ))
114+ rv = append (rv , adminUser )
115+ }
116+ pageToken , err = marshalSkipToken (len (adminUsers ), skip , b )
117+ if err != nil {
118+ return nil , "" , nil , err
119+ }
120+ default :
121+ return nil , "" , nil , fmt .Errorf ("baton-jumpcloud: unknown page state: %s" , b .Current ().ResourceTypeID )
122+ }
123+
124+ return rv , pageToken , nil , nil
125+ }
126+
127+ func (o * userResourceType ) adminUserResource (ctx context.Context , user * jcapi1.Userreturn ) (* v2.Resource , error ) {
128+ profile := map [string ]interface {}{
129+ "id" : user .GetId (),
130+ }
131+
132+ if user .HasOrganization () {
133+ profile ["organization" ] = user .GetOrganization ()
134+ }
135+
136+ userTraitOps := []sdkResources.UserTraitOption {
137+ sdkResources .WithUserProfile (profile ),
66138 }
67139
68- pageToken , err := marshalSkipToken (len (list .Results ), skip , b )
140+ status := v2 .UserTrait_Status_STATUS_ENABLED
141+ if user .GetSuspended () {
142+ status = v2 .UserTrait_Status_STATUS_DISABLED
143+ }
144+ userTraitOps = append (userTraitOps , sdkResources .WithStatus (status ))
145+
146+ email := user .GetEmail ()
147+ if email != "" {
148+ userTraitOps = append (userTraitOps , sdkResources .WithEmail (email , true ))
149+ }
150+
151+ r , err := sdkResources .NewUserResource (
152+ fmt .Sprintf ("%s %s" , user .GetFirstname (), user .GetLastname ()),
153+ o .resourceType ,
154+ user .GetId (),
155+ userTraitOps ,
156+ )
69157 if err != nil {
70- return nil , "" , nil , err
158+ return nil , err
71159 }
72160
73- return rv , pageToken , nil , nil
161+ return r , nil
74162}
75163
76164func (o * userResourceType ) userResource (ctx context.Context , user * jcapi1.Systemuserreturn ) (* v2.Resource , error ) {
0 commit comments