Skip to content

Commit a70b838

Browse files
authored
SMQ-2924 - Allow bulk deleting of invitations from repository (#2942)
Signed-off-by: Felix Gateru <[email protected]>
1 parent c50221a commit a70b838

File tree

6 files changed

+89
-65
lines changed

6 files changed

+89
-65
lines changed

domains/domains.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,8 @@ type Repository interface {
263263
// UpdateRejection updates an invitation by setting the rejection time.
264264
UpdateRejection(ctx context.Context, invitation Invitation) (err error)
265265

266-
// Delete deletes an invitation.
267-
DeleteInvitation(ctx context.Context, userID, domainID string) (err error)
266+
// DeleteUsersInvitations deletes invitation to a provided domain for users with provided user IDs.
267+
DeleteUsersInvitations(ctx context.Context, domainID string, userID ...string) (err error)
268268

269269
roles.Repository
270270
}

domains/mocks/repository.go

Lines changed: 28 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

domains/postgres/invitations.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,18 @@ func (repo domainRepo) UpdateRejection(ctx context.Context, invitation domains.I
150150
return nil
151151
}
152152

153-
func (repo domainRepo) DeleteInvitation(ctx context.Context, inviteeUserID, domain string) (err error) {
154-
q := `DELETE FROM invitations WHERE invitee_user_id = $1 AND domain_id = $2`
153+
func (repo domainRepo) DeleteUsersInvitations(ctx context.Context, domain string, inviteeUserIDs ...string) (err error) {
154+
if len(inviteeUserIDs) == 0 {
155+
return repoerr.ErrNotFound
156+
}
155157

156-
result, err := repo.db.ExecContext(ctx, q, inviteeUserID, domain)
158+
q := `DELETE FROM invitations WHERE domain_id = :domain_id AND invitee_user_id = ANY(:invitee_user_ids);`
159+
160+
params := map[string]any{
161+
"invitee_user_ids": inviteeUserIDs,
162+
"domain_id": domain,
163+
}
164+
result, err := repo.db.NamedExecContext(ctx, q, params)
157165
if err != nil {
158166
return postgres.HandleError(repoerr.ErrRemoveEntity, err)
159167
}

domains/postgres/invitations_test.go

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ func TestUpdateRejection(t *testing.T) {
761761
}
762762
}
763763

764-
func TestDeleteInvitation(t *testing.T) {
764+
func TestDeleteUsersInvitations(t *testing.T) {
765765
t.Cleanup(func() {
766766
_, err := db.Exec("DELETE FROM invitations")
767767
require.Nil(t, err, fmt.Sprintf("clean invitations unexpected error: %s", err))
@@ -772,48 +772,58 @@ func TestDeleteInvitation(t *testing.T) {
772772

773773
dom := saveDomain(t, repo)
774774

775-
invitation := domains.Invitation{
776-
InvitedBy: testsutil.GenerateUUID(t),
777-
InviteeUserID: testsutil.GenerateUUID(t),
778-
DomainID: dom.ID,
779-
DomainName: dom.Name,
780-
RoleID: testsutil.GenerateUUID(t),
781-
RoleName: roleName,
782-
CreatedAt: time.Now(),
775+
num := 10
776+
items := make([]domains.Invitation, 0, num)
777+
778+
for i := 0; i < num; i++ {
779+
invitation := domains.Invitation{
780+
InvitedBy: testsutil.GenerateUUID(t),
781+
InviteeUserID: testsutil.GenerateUUID(t),
782+
DomainID: dom.ID,
783+
DomainName: dom.Name,
784+
RoleID: testsutil.GenerateUUID(t),
785+
RoleName: roleName,
786+
CreatedAt: time.Now(),
787+
}
788+
err := repo.SaveInvitation(context.Background(), invitation)
789+
require.Nil(t, err, fmt.Sprintf("create invitation unexpected error: %s", err))
790+
items = append(items, invitation)
783791
}
784-
err := repo.SaveInvitation(context.Background(), invitation)
785-
require.Nil(t, err, fmt.Sprintf("create invitation unexpected error: %s", err))
786792

787793
cases := []struct {
788-
desc string
789-
invitation domains.Invitation
790-
err error
794+
desc string
795+
domainID string
796+
userIDs []string
797+
err error
791798
}{
792799
{
793-
desc: "delete invitation successfully",
794-
invitation: domains.Invitation{
795-
InviteeUserID: invitation.InviteeUserID,
796-
DomainID: invitation.DomainID,
797-
},
798-
err: nil,
800+
desc: "delete one invitation successfully",
801+
domainID: dom.ID,
802+
userIDs: []string{items[0].InviteeUserID},
803+
err: nil,
799804
},
800805
{
801-
desc: "delete invitation with invalid invitation id",
802-
invitation: domains.Invitation{
803-
InviteeUserID: testsutil.GenerateUUID(t),
804-
DomainID: testsutil.GenerateUUID(t),
805-
},
806-
err: repoerr.ErrNotFound,
806+
desc: "delete multiple invitations successfully",
807+
domainID: dom.ID,
808+
userIDs: []string{items[1].InviteeUserID, items[2].InviteeUserID, items[3].InviteeUserID},
809+
err: nil,
807810
},
808811
{
809-
desc: "delete invitation with empty invitation id",
810-
invitation: domains.Invitation{},
811-
err: repoerr.ErrNotFound,
812+
desc: "delete invitation with invalid invitation id",
813+
domainID: dom.ID,
814+
userIDs: []string{testsutil.GenerateUUID(t)},
815+
err: repoerr.ErrNotFound,
816+
},
817+
{
818+
desc: "delete invitation with empty user id",
819+
domainID: dom.ID,
820+
userIDs: []string{},
821+
err: repoerr.ErrNotFound,
812822
},
813823
}
814824
for _, tc := range cases {
815825
t.Run(tc.desc, func(t *testing.T) {
816-
err := repo.DeleteInvitation(context.Background(), tc.invitation.InviteeUserID, tc.invitation.DomainID)
826+
err := repo.DeleteUsersInvitations(context.Background(), tc.domainID, tc.userIDs...)
817827
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
818828
})
819829
}

domains/service.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ func (svc *service) RejectInvitation(ctx context.Context, session authn.Session,
306306

307307
func (svc *service) DeleteInvitation(ctx context.Context, session authn.Session, inviteeUserID, domainID string) error {
308308
if session.UserID == inviteeUserID {
309-
if err := svc.repo.DeleteInvitation(ctx, inviteeUserID, domainID); err != nil {
309+
if err := svc.repo.DeleteUsersInvitations(ctx, domainID, inviteeUserID); err != nil {
310310
return errors.Wrap(svcerr.ErrRemoveEntity, err)
311311
}
312312
return nil
@@ -325,7 +325,7 @@ func (svc *service) DeleteInvitation(ctx context.Context, session authn.Session,
325325
return errors.Wrap(svcerr.ErrRemoveEntity, svcerr.ErrInvitationAlreadyRejected)
326326
}
327327

328-
if err := svc.repo.DeleteInvitation(ctx, inviteeUserID, domainID); err != nil {
328+
if err := svc.repo.DeleteUsersInvitations(ctx, domainID, inviteeUserID); err != nil {
329329
return errors.Wrap(svcerr.ErrRemoveEntity, err)
330330
}
331331

@@ -334,11 +334,10 @@ func (svc *service) DeleteInvitation(ctx context.Context, session authn.Session,
334334

335335
// Add addition removal of user from invitations.
336336
func (svc *service) RemoveEntityMembers(ctx context.Context, session authn.Session, entityID string, members []string) error {
337-
for _, member := range members {
338-
if err := svc.repo.DeleteInvitation(ctx, member, entityID); err != nil && err != repoerr.ErrNotFound {
339-
return err
340-
}
337+
if err := svc.repo.DeleteUsersInvitations(ctx, entityID, members...); err != nil && err != repoerr.ErrNotFound {
338+
return err
341339
}
340+
342341
return svc.ProvisionManageService.RemoveEntityMembers(ctx, session, entityID, members)
343342
}
344343

@@ -358,10 +357,8 @@ func (svc *service) RoleRemoveMembers(ctx context.Context, session authn.Session
358357
}
359358
}
360359

361-
for _, memberID := range members {
362-
if err := svc.repo.DeleteInvitation(ctx, memberID, entityID); err != nil && err != repoerr.ErrNotFound {
363-
return err
364-
}
360+
if err := svc.repo.DeleteUsersInvitations(ctx, entityID, members...); err != nil && err != repoerr.ErrNotFound {
361+
return err
365362
}
366363

367364
return svc.ProvisionManageService.RoleRemoveMembers(ctx, session, entityID, roleID, members)

domains/service_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ func TestDeleteInvitation(t *testing.T) {
11141114
for _, tc := range cases {
11151115
t.Run(tc.desc, func(t *testing.T) {
11161116
repoCall := drepo.On("RetrieveInvitation", context.Background(), mock.Anything, mock.Anything).Return(tc.resp, tc.retrieveInvitationErr)
1117-
repoCall1 := drepo.On("DeleteInvitation", context.Background(), mock.Anything, mock.Anything).Return(tc.deleteInvitationErr)
1117+
repoCall1 := drepo.On("DeleteUsersInvitations", context.Background(), mock.Anything, mock.Anything).Return(tc.deleteInvitationErr)
11181118
err := svc.DeleteInvitation(context.Background(), tc.session, tc.userID, tc.domainID)
11191119
assert.True(t, errors.Contains(err, tc.err))
11201120
repoCall.Unset()

0 commit comments

Comments
 (0)