Skip to content

Commit 66588cd

Browse files
Create contact role
Signed-off-by: Lukasz Gryglicki <[email protected]> Assisted by [OpenAI](https://platform.openai.com/) Assisted by [GitHub Copilot](https://github.com/features/copilot)
1 parent 5296a0e commit 66588cd

File tree

2 files changed

+110
-3
lines changed

2 files changed

+110
-3
lines changed

cla-backend-go/v2/cla_manager/emails.go

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,8 @@ func (s *service) SendDesigneeEmailToUserWithNoLFID(ctx context.Context, input D
313313
// Parse the provided user's name
314314
userFirstName, userLastName := utils.GetFirstAndLastName(input.userWithNoLFIDName)
315315

316-
return acsClient.SendUserInvite(ctx, &v2AcsService.SendUserInviteInput{
316+
// Send invitation for the primary CLA role (e.g., cla-manager-designee)
317+
inviteErr := acsClient.SendUserInvite(ctx, &v2AcsService.SendUserInviteInput{
317318
InviteUserFirstName: userFirstName,
318319
InviteUserLastName: userLastName,
319320
InviteUserEmail: input.userWithNoLFIDEmail,
@@ -326,6 +327,48 @@ func (s *service) SendDesigneeEmailToUserWithNoLFID(ctx context.Context, input D
326327
EmailContent: body,
327328
Automate: false,
328329
})
330+
if inviteErr != nil {
331+
log.WithFields(f).WithError(inviteErr).Warnf("failed to send primary role invitation")
332+
return inviteErr
333+
}
334+
335+
// Also send invitation for the "contact" role which is required to access Corporate Console
336+
// This is sent at organization scope (not project|organization)
337+
contactSubject := fmt.Sprintf("EasyCLA: Invitation to access Corporate Console for %s", input.companyName)
338+
contactBody, contactBodyErr := emails.RenderV2ToCLAManagerDesigneeTemplate(s.emailTemplateService, input.projectSFIDs,
339+
emails.V2ToCLAManagerDesigneeTemplateParams{
340+
CommonEmailParams: emails.CommonEmailParams{
341+
RecipientName: input.userWithNoLFIDName,
342+
CompanyName: input.companyName,
343+
},
344+
Contributor: input.contributorModel,
345+
}, emails.V2DesigneeToUserWithNoLFIDTemplate, emails.V2DesigneeToUserWithNoLFIDTemplateName)
346+
347+
if contactBodyErr != nil {
348+
log.WithFields(f).WithError(contactBodyErr).Warnf("failed to render contact role invitation email template")
349+
// Don't return error, as the primary invitation was successful
350+
} else {
351+
log.WithFields(f).Debug("sending contact role invite request...")
352+
contactInviteErr := acsClient.SendUserInvite(ctx, &v2AcsService.SendUserInviteInput{
353+
InviteUserFirstName: userFirstName,
354+
InviteUserLastName: userLastName,
355+
InviteUserEmail: input.userWithNoLFIDEmail,
356+
RoleName: utils.ContactRole,
357+
Scope: "organization", // Contact role is at organization scope only
358+
ProjectSFID: "", // Not applicable for organization scope
359+
OrganizationSFID: input.organizationID,
360+
InviteType: "userinvite",
361+
Subject: contactSubject,
362+
EmailContent: contactBody,
363+
Automate: false,
364+
})
365+
if contactInviteErr != nil {
366+
log.WithFields(f).WithError(contactInviteErr).Warnf("failed to send contact role invitation, but primary invitation succeeded")
367+
// Don't return error, as the primary invitation was successful
368+
}
369+
}
370+
371+
return nil
329372
}
330373

331374
// sendEmailToUserWithNoLFID helper function to send email to a given user with no LFID
@@ -364,8 +407,9 @@ func (s *service) SendEmailToUserWithNoLFID(ctx context.Context, input EmailToUs
364407
userFirstName, userLastName := utils.GetFirstAndLastName(input.userWithNoLFIDName)
365408

366409
log.WithFields(f).Debug("sending user invite request...")
367-
//return acsClient.SendUserInvite(ctx, &userWithNoLFIDEmail, role, utils.ProjectOrgScope, projectID, organizationID, "userinvite", &subject, &body, automate)
368-
return acsClient.SendUserInvite(ctx, &v2AcsService.SendUserInviteInput{
410+
411+
// Send invitation for the primary CLA role (e.g., cla-manager-designee)
412+
inviteErr := acsClient.SendUserInvite(ctx, &v2AcsService.SendUserInviteInput{
369413
InviteUserFirstName: userFirstName,
370414
InviteUserLastName: userLastName,
371415
InviteUserEmail: input.userWithNoLFIDEmail,
@@ -378,4 +422,45 @@ func (s *service) SendEmailToUserWithNoLFID(ctx context.Context, input EmailToUs
378422
EmailContent: body,
379423
Automate: false,
380424
})
425+
if inviteErr != nil {
426+
log.WithFields(f).WithError(inviteErr).Warnf("failed to send primary role invitation")
427+
return inviteErr
428+
}
429+
430+
// Also send invitation for the "contact" role which is required to access Corporate Console
431+
// This is sent at organization scope (not project|organization)
432+
contactSubject := fmt.Sprintf("EasyCLA: Invitation to access Corporate Console for %s", input.companyName)
433+
contactBody, contactBodyErr := emails.RenderV2CLAManagerToUserWithNoLFIDTemplate(s.emailTemplateService, input.projectID, emails.V2CLAManagerToUserWithNoLFIDTemplateParams{
434+
CommonEmailParams: emails.CommonEmailParams{
435+
RecipientName: input.userWithNoLFIDName,
436+
CompanyName: input.companyName,
437+
},
438+
RequesterUserName: input.requesterUsername,
439+
RequesterEmail: input.requesterEmail,
440+
})
441+
if contactBodyErr != nil {
442+
log.WithFields(f).WithError(contactBodyErr).Warnf("failed to render contact role invitation email template")
443+
// Don't return error, as the primary invitation was successful
444+
} else {
445+
log.WithFields(f).Debug("sending contact role invite request...")
446+
contactInviteErr := acsClient.SendUserInvite(ctx, &v2AcsService.SendUserInviteInput{
447+
InviteUserFirstName: userFirstName,
448+
InviteUserLastName: userLastName,
449+
InviteUserEmail: input.userWithNoLFIDEmail,
450+
RoleName: utils.ContactRole,
451+
Scope: "organization", // Contact role is at organization scope only
452+
ProjectSFID: "", // Not applicable for organization scope
453+
OrganizationSFID: input.organizationID,
454+
InviteType: "userinvite",
455+
Subject: contactSubject,
456+
EmailContent: contactBody,
457+
Automate: false,
458+
})
459+
if contactInviteErr != nil {
460+
log.WithFields(f).WithError(contactInviteErr).Warnf("failed to send contact role invitation, but primary invitation succeeded")
461+
// Don't return error, as the primary invitation was successful
462+
}
463+
}
464+
465+
return nil
381466
}

cla-backend-go/v2/cla_manager/service.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,28 @@ func (s *service) CreateCLAManagerDesignee(ctx context.Context, companyID string
414414
log.WithFields(f).Debugf("created user role organization scope for user: %s, with role: %s with role ID: %s using project|org: %s|%s...",
415415
userEmail, utils.CLADesigneeRole, roleID, projectSFID, v1CompanyModel.CompanyExternalID)
416416

417+
// Also assign the "contact" role which is required to access the Corporate Console
418+
log.WithFields(f).Debugf("loading role ID for %s...", utils.ContactRole)
419+
contactRoleID, contactErr := acServiceClient.GetRoleID(utils.ContactRole)
420+
if contactErr != nil {
421+
log.WithFields(f).Warnf("Problem getting role ID for contact role, error: %+v - continuing without contact role", contactErr)
422+
} else {
423+
log.WithFields(f).Debugf("creating contact role organization scope for user: %s, with role: %s with role ID: %s using org: %s...",
424+
userEmail, utils.ContactRole, contactRoleID, v1CompanyModel.CompanyExternalID)
425+
contactScopeErr := orgClient.CreateOrgUserRoleOrgScope(ctx, userEmail, v1CompanyModel.CompanyExternalID, contactRoleID)
426+
if contactScopeErr != nil {
427+
// Ignore conflict - role has already been assigned - otherwise, log error but don't fail
428+
if _, ok := contactScopeErr.(*organizations.CreateOrgUsrRoleScopesConflict); !ok {
429+
log.WithFields(f).Warnf("problem creating contact role org scope for email: %s, companySFID: %s, error: %+v - continuing without contact role", userEmail, v1CompanyModel.CompanyExternalID, contactScopeErr)
430+
} else {
431+
log.WithFields(f).Debugf("contact role already assigned for user: %s, companySFID: %s", userEmail, v1CompanyModel.CompanyExternalID)
432+
}
433+
} else {
434+
log.WithFields(f).Debugf("successfully created contact role organization scope for user: %s, with role: %s with role ID: %s using org: %s",
435+
userEmail, utils.ContactRole, contactRoleID, v1CompanyModel.CompanyExternalID)
436+
}
437+
}
438+
417439
// Log Event
418440
s.eventService.LogEventWithContext(ctx,
419441
&events.LogEventArgs{

0 commit comments

Comments
 (0)