{satellite/console,web/satellite}: show error for project invite dupes
This change fixes an issue where a new project member invitation would silently replace an older one that has the same project ID and email if the email did not belong to a registered user. Additionally, the satellite frontend has been updated to display more descriptive error messages for project member invitations. Change-Id: I32b582c40c0028b8eedf2aed4b5bfb43501594b4
This commit is contained in:
parent
fbda13c752
commit
c79d1b0d2f
@ -75,7 +75,7 @@ const (
|
||||
projInviteInvalidErrMsg = "The invitation has expired or is invalid"
|
||||
projInviteAlreadyMemberErrMsg = "You are already a member of the project"
|
||||
projInviteResponseInvalidErrMsg = "Invalid project member invitation response"
|
||||
projInviteActiveErrMsg = "The invitation for '%s' has not expired yet"
|
||||
projInviteExistsErrMsg = "An active invitation for '%s' already exists"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -143,8 +143,8 @@ var (
|
||||
// or has expired.
|
||||
ErrProjectInviteInvalid = errs.Class("invalid project invitation")
|
||||
|
||||
// ErrProjectInviteActive occurs when trying to reinvite a user whose invitation hasn't expired yet.
|
||||
ErrProjectInviteActive = errs.Class("project invitation active")
|
||||
// ErrAlreadyInvited occurs when trying to invite a user who already has an unexpired invitation.
|
||||
ErrAlreadyInvited = errs.Class("user is already invited")
|
||||
)
|
||||
|
||||
// Service is handling accounts related logic.
|
||||
@ -3570,7 +3570,6 @@ func (s *Service) RespondToProjectInvitation(ctx context.Context, projectID uuid
|
||||
|
||||
// InviteProjectMembers invites users by email to given project.
|
||||
// If an invitation already exists and has expired, it will be replaced and the user will be sent a new email.
|
||||
// Email addresses not belonging to a user are ignored.
|
||||
// projectID here may be project.PublicID or project.ID.
|
||||
func (s *Service) InviteProjectMembers(ctx context.Context, projectID uuid.UUID, emails []string) (invites []ProjectInvitation, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
@ -3588,6 +3587,14 @@ func (s *Service) InviteProjectMembers(ctx context.Context, projectID uuid.UUID,
|
||||
var users []*User
|
||||
var newUserEmails []string
|
||||
for _, email := range emails {
|
||||
invite, err := s.store.ProjectInvitations().Get(ctx, projectID, email)
|
||||
if err != nil && !errs.Is(err, sql.ErrNoRows) {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
if invite != nil && !s.IsProjectInvitationExpired(invite) {
|
||||
return nil, ErrAlreadyInvited.New(projInviteExistsErrMsg, email)
|
||||
}
|
||||
|
||||
invitedUser, err := s.store.Users().GetByEmail(ctx, email)
|
||||
if err == nil {
|
||||
_, err = s.isProjectMember(ctx, invitedUser.ID, projectID)
|
||||
@ -3596,14 +3603,6 @@ func (s *Service) InviteProjectMembers(ctx context.Context, projectID uuid.UUID,
|
||||
} else if err == nil {
|
||||
return nil, ErrAlreadyMember.New("%s is already a member", email)
|
||||
}
|
||||
|
||||
invite, err := s.store.ProjectInvitations().Get(ctx, projectID, email)
|
||||
if err != nil && !errs.Is(err, sql.ErrNoRows) {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
if invite != nil && !s.IsProjectInvitationExpired(invite) {
|
||||
return nil, ErrProjectInviteActive.New(projInviteActiveErrMsg, invitedUser.Email)
|
||||
}
|
||||
users = append(users, invitedUser)
|
||||
} else if errs.Is(err, sql.ErrNoRows) {
|
||||
newUserEmails = append(newUserEmails, email)
|
||||
|
@ -2064,7 +2064,7 @@ func TestProjectInvitations(t *testing.T) {
|
||||
|
||||
// resending an active invitation should fail.
|
||||
invites, err = service.InviteProjectMembers(ctx2, project.ID, []string{user3.Email})
|
||||
require.True(t, console.ErrProjectInviteActive.Has(err))
|
||||
require.True(t, console.ErrAlreadyInvited.Has(err))
|
||||
require.Empty(t, invites)
|
||||
|
||||
// expire the invitation.
|
||||
|
@ -188,7 +188,7 @@ async function onAddUsersClick(): Promise<void> {
|
||||
}
|
||||
|
||||
if (emailArray.includes(usersStore.state.user.email)) {
|
||||
await notify.error(`Error during adding project members. You can't add yourself to the project`, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
await notify.error(`Error adding project members. You can't add yourself to the project`, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
isLoading.value = false;
|
||||
|
||||
return;
|
||||
@ -196,8 +196,8 @@ async function onAddUsersClick(): Promise<void> {
|
||||
|
||||
try {
|
||||
await pmStore.inviteMembers(emailArray, projectsStore.state.selectedProject.id);
|
||||
} catch (_) {
|
||||
await notify.error(`Error during adding project members.`, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
} catch (error) {
|
||||
await notify.error(`Error adding project members. ${error.message}`, AnalyticsErrorEventSource.ADD_PROJECT_MEMBER_MODAL);
|
||||
isLoading.value = false;
|
||||
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user