@@ -2,8 +2,8 @@ package connector
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
6- "slices"
77 "strconv"
88
99 v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
@@ -34,6 +34,14 @@ type roleBuilder struct {
3434 disableCustomRolesSync bool
3535}
3636
37+ func GetRoleResourceID (roleId string , targetEnv workato.Environment , configEnv workato.Environment ) string {
38+ // For backward compatibility, do not change the role IDs if the environment configuration is set to a specific environment.
39+ if configEnv != workato .All {
40+ return roleId
41+ }
42+ return fmt .Sprintf ("%s-%s" , roleId , targetEnv .String ())
43+ }
44+
3745func (o * roleBuilder ) ResourceType (ctx context.Context ) * v2.ResourceType {
3846 return roleResourceType
3947}
@@ -47,6 +55,13 @@ func (o *roleBuilder) List(ctx context.Context, _ *v2.ResourceId, attr rs.SyncOp
4755
4856 var nextToken string
4957
58+ var envs []workato.Environment
59+ if o .env == workato .All {
60+ envs = workato .AllEnvironments ()
61+ } else {
62+ envs = append (envs , o .env )
63+ }
64+
5065 if ! o .disableCustomRolesSync {
5166 var roles []client.Role
5267 var err error
@@ -61,23 +76,28 @@ func (o *roleBuilder) List(ctx context.Context, _ *v2.ResourceId, attr rs.SyncOp
6176 return nil , nil , err
6277 }
6378
64- for _ , role := range roles {
65- us , err := roleResource (& role )
66- if err != nil {
67- return nil , nil , err
79+ for _ , targetEnv := range envs {
80+ for _ , role := range roles {
81+ us , err := roleResource (& role , o .env , targetEnv )
82+ if err != nil {
83+ return nil , nil , err
84+ }
85+ rv = append (rv , us )
6886 }
69- rv = append (rv , us )
7087 }
7188 }
7289
73- // Add base roles
74- for _ , role := range workato .BaseRoles {
75- us , err := workatoBaseRoleResource (& role )
76- if err != nil {
77- return nil , nil , err
90+ if nextToken == "" {
91+ // Add base roles
92+ for _ , targetEnv := range envs {
93+ for _ , role := range workato .BaseRoles {
94+ us , err := workatoBaseRoleResource (& role , o .env , targetEnv )
95+ if err != nil {
96+ return nil , nil , err
97+ }
98+ rv = append (rv , us )
99+ }
78100 }
79-
80- rv = append (rv , us )
81101 }
82102
83103 return rv , & rs.SyncOpResults {
@@ -180,73 +200,62 @@ func (o *roleBuilder) Grants(ctx context.Context, resource *v2.Resource, attr rs
180200 return rv , nil , nil
181201}
182202
183- func (o * roleBuilder ) Grant (ctx context.Context , resource * v2.Resource , entitlement * v2.Entitlement ) ([]* v2.Grant , annotations.Annotations , error ) {
184- // Grant a role to a collaborator
185- if resource .Id .ResourceType == collaboratorResourceType .Id {
186- grants := make ([]* v2.Grant , 0 )
187-
188- roleName := entitlement .Resource .Id .Resource
189- userID , err := strconv .Atoi (resource .Id .Resource )
190- if err != nil {
191- return nil , nil , err
192- }
203+ func (o * roleBuilder ) Grant (ctx context.Context , principal * v2.Resource , entitlement * v2.Entitlement ) ([]* v2.Grant , annotations.Annotations , error ) {
204+ if principal .Id .ResourceType != collaboratorResourceType .Id {
205+ return nil , nil , fmt .Errorf ("grant not implemented for %s" , principal .Id .ResourceType )
206+ }
193207
194- collaborator , err := o .client .GetCollaboratorPrivileges (ctx , userID )
195- if err != nil {
196- return nil , nil , err
197- }
208+ // Grant a role to a collaborator
209+ userID , err := strconv .Atoi (principal .Id .Resource )
210+ if err != nil {
211+ return nil , nil , err
212+ }
198213
199- roles := toSimpleRole (collaborator )
214+ roleTrait , err := rs .GetRoleTrait (entitlement .Resource )
215+ if err != nil {
216+ return nil , nil , err
217+ }
218+ profile := roleTrait .GetProfile ()
219+ if profile == nil {
220+ return nil , nil , fmt .Errorf ("role profile not found" )
221+ }
222+ roleName , ok := profile .AsMap ()["name" ].(string )
223+ if ! ok {
224+ return nil , nil , fmt .Errorf ("role name is missing or invalid" )
225+ }
226+ environmentType , ok := profile .AsMap ()["environment" ].(string )
227+ if ! ok {
228+ return nil , nil , fmt .Errorf ("environment value is missing or invalid" )
229+ }
200230
201- newRole := client.SimpleRole {
231+ roles := []client.SimpleRole {
232+ {
202233 RoleName : roleName ,
203- EnvironmentType : o .env .String (),
204- }
205-
206- index := slices .IndexFunc (roles , func (other client.SimpleRole ) bool {
207- return other .Equals (newRole )
208- })
209-
210- if index >= 0 {
211- return []* v2.Grant {}, annotations .New (& v2.GrantAlreadyExists {}), nil
212- }
213-
214- // Workato just accept one role per environment
215- sameEnvIndex := slices .IndexFunc (roles , func (other client.SimpleRole ) bool {
216- return other .EnvironmentType == o .env .String ()
217- })
218-
219- if sameEnvIndex >= 0 {
220- roles [sameEnvIndex ] = newRole
221- } else {
222- roles = append (roles , newRole )
223- }
224-
225- err = o .client .UpdateCollaboratorRoles (ctx , userID , roles )
226- if err != nil {
227- return nil , nil , err
228- }
229-
230- collaboratorId , err := rs .NewResourceID (collaboratorResourceType , userID )
231- if err != nil {
232- return nil , nil , err
233- }
234-
235- newGrant := grant .NewGrant (
236- resource ,
237- collaboratorHasRoleEntitlement ,
238- collaboratorId ,
239- grant .WithGrantMetadata (map [string ]interface {}{
240- "environment_type" : o .env .String (),
241- }),
242- )
243-
244- grants = append (grants , newGrant )
234+ EnvironmentType : environmentType ,
235+ },
236+ }
245237
246- return grants , nil , nil
238+ l := ctxzap .Extract (ctx )
239+ rolesJSON , err := json .Marshal (roles )
240+ if err != nil {
241+ return nil , nil , err
242+ }
243+ l .Info ("Updating collaborator roles" , zap .Int ("user_id" , userID ), zap .String ("roles" , string (rolesJSON )))
244+ err = o .client .UpdateCollaboratorRoles (ctx , userID , roles )
245+ if err != nil {
246+ return nil , nil , err
247247 }
248248
249- return nil , nil , fmt .Errorf ("grant not implemented for %s" , resource .Id .ResourceType )
249+ newGrant := grant .NewGrant (
250+ entitlement .Resource ,
251+ collaboratorHasRoleEntitlement ,
252+ principal .Id ,
253+ grant .WithGrantMetadata (map [string ]interface {}{
254+ "environment_type" : environmentType ,
255+ }),
256+ )
257+
258+ return []* v2.Grant {newGrant }, nil , nil
250259}
251260
252261func (o * roleBuilder ) Revoke (_ context.Context , grant * v2.Grant ) (annotations.Annotations , error ) {
@@ -262,10 +271,17 @@ func newRoleBuilder(client *client.WorkatoClient, env workato.Environment, disab
262271 }
263272}
264273
265- func roleResource (role * client.Role ) (* v2.Resource , error ) {
274+ func roleResource (role * client.Role , envConfig workato.Environment , targetEnv workato.Environment ) (* v2.Resource , error ) {
275+ if targetEnv == workato .All {
276+ return nil , fmt .Errorf ("target environment %s is not supported for role resources" , targetEnv .String ())
277+ }
278+
279+ id := strconv .Itoa (role .Id )
280+
266281 profile := map [string ]interface {}{
267- "id" : role . Id ,
282+ "id" : id ,
268283 "name" : role .Name ,
284+ "environment" : targetEnv .String (),
269285 "create_at" : role .CreatedAt .String (),
270286 "inheritable" : role .Inheritable ,
271287 "updated_at" : role .UpdatedAt .String (),
@@ -276,9 +292,9 @@ func roleResource(role *client.Role) (*v2.Resource, error) {
276292 }
277293
278294 ret , err := rs .NewRoleResource (
279- role .Name ,
295+ fmt . Sprintf ( "%s (%s)" , role .Name , targetEnv . String ()) ,
280296 roleResourceType ,
281- role . Id ,
297+ GetRoleResourceID ( id , targetEnv , envConfig ) ,
282298 traits ,
283299 )
284300 if err != nil {
@@ -288,20 +304,28 @@ func roleResource(role *client.Role) (*v2.Resource, error) {
288304 return ret , nil
289305}
290306
291- func workatoBaseRoleResource (role * workato.Role ) (* v2.Resource , error ) {
307+ // workatoBaseRoleResource creates a new role resource for a base role.
308+ // envConfig is the environment configured for the connector.
309+ // targetEnv is the environment to create the role resource for.
310+ func workatoBaseRoleResource (role * workato.Role , envConfig workato.Environment , targetEnv workato.Environment ) (* v2.Resource , error ) {
311+ if targetEnv == workato .All {
312+ return nil , fmt .Errorf ("target environment %s is not supported for base roles" , targetEnv .String ())
313+ }
314+
292315 profile := map [string ]interface {}{
293- "id" : role .RoleName ,
294- "name" : role .RoleName ,
316+ "id" : role .RoleName ,
317+ "name" : role .RoleName ,
318+ "environment" : targetEnv .String (),
295319 }
296320
297321 traits := []rs.RoleTraitOption {
298322 rs .WithRoleProfile (profile ),
299323 }
300324
301325 ret , err := rs .NewRoleResource (
302- role .RoleName ,
326+ fmt . Sprintf ( "%s (%s)" , role .RoleName , targetEnv . String ()) ,
303327 roleResourceType ,
304- role .RoleName ,
328+ GetRoleResourceID ( role .RoleName , targetEnv , envConfig ) ,
305329 traits ,
306330 )
307331 if err != nil {
@@ -310,12 +334,3 @@ func workatoBaseRoleResource(role *workato.Role) (*v2.Resource, error) {
310334
311335 return ret , nil
312336}
313-
314- func toSimpleRole (collaboratorRoles []* client.CollaboratorPrivilege ) []client.SimpleRole {
315- roles := make ([]client.SimpleRole , 0 )
316- for _ , role := range collaboratorRoles {
317- roles = append (roles , role .SimpleRole ())
318- }
319-
320- return roles
321- }
0 commit comments