From 6014179e6ff799fd1adb07db27c9f5c371ec8431 Mon Sep 17 00:00:00 2001
From: Pavlo Voroniak
Date: Fri, 11 Apr 2025 00:15:23 +0300
Subject: [PATCH 1/2] [DEV-5227] check if member is in use
---
store/sqlstore/cc_member_store.go | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/store/sqlstore/cc_member_store.go b/store/sqlstore/cc_member_store.go
index 01a051a6..bb310e56 100644
--- a/store/sqlstore/cc_member_store.go
+++ b/store/sqlstore/cc_member_store.go
@@ -392,7 +392,21 @@ from m
// TODO add force
func (s SqlMemberStore) Delete(ctx context.Context, queueId, id int64) model.AppError {
- var cnt int64
+ var cntCheck, cnt int64
+
+ check, err := s.GetMaster().WithContext(ctx).Exec(`select 1 from call_center.cc_member_attempt a where a.member_id = :Id and a.state != 'leaving' for update`,
+ map[string]interface{}{"Id": id})
+ if err != nil {
+ return model.NewCustomCodeError("store.sql_member.delete.app_error", fmt.Sprintf("Id=%v, %s", id, err.Error()), extractCodeFromErr(err))
+ }
+ cntCheck, err = check.RowsAffected()
+ if err != nil {
+ return model.NewCustomCodeError("store.sql_member.delete.app_error", fmt.Sprintf("Id=%v, %s", id, err.Error()), extractCodeFromErr(err))
+ }
+
+ if cntCheck == 0 {
+ return model.NewCustomCodeError("store.sql_member.delete.app_error", fmt.Sprintf("Id=%v, member reserved", id), http.StatusForbidden)
+ }
res, err := s.GetMaster().WithContext(ctx).Exec(`delete
from call_center.cc_member c
where c.id = :Id
From da44d9fd77c2df2bcf8bcfdd1bcd2aa6c57e4239 Mon Sep 17 00:00:00 2001
From: "i.navrotskyj"
Date: Fri, 11 Apr 2025 09:03:09 +0300
Subject: [PATCH 2/2] [DEV-5227] check if member is in queue
---
app/cc_member.go | 8 ++++++--
grpc_api/cc_member.go | 4 +++-
store/sqlstore/cc_member_store.go | 27 ++++++++-------------------
store/store.go | 2 +-
4 files changed, 18 insertions(+), 23 deletions(-)
diff --git a/app/cc_member.go b/app/cc_member.go
index 4a23a618..66f6429d 100644
--- a/app/cc_member.go
+++ b/app/cc_member.go
@@ -137,14 +137,18 @@ func (app *App) PatchMember(ctx context.Context, domainId, queueId, id int64, pa
return oldMember, nil
}
-func (app *App) RemoveMember(ctx context.Context, domainId, queueId, id int64) (*model.Member, model.AppError) {
+func (app *App) RemoveMember(ctx context.Context, domainId, queueId, id int64, force bool) (*model.Member, model.AppError) {
member, err := app.GetMember(ctx, domainId, queueId, id)
if err != nil {
return nil, err
}
- err = app.Store.Member().Delete(ctx, queueId, id)
+ if !force && member.Reserved {
+ return nil, model.NewBadRequestError("member.reserved", "Member is reserved")
+ }
+
+ err = app.Store.Member().Delete(ctx, queueId, id, force)
if err != nil {
return nil, err
}
diff --git a/grpc_api/cc_member.go b/grpc_api/cc_member.go
index 9a023d9e..0471509e 100644
--- a/grpc_api/cc_member.go
+++ b/grpc_api/cc_member.go
@@ -521,8 +521,10 @@ func (api *member) DeleteMember(ctx context.Context, in *engine.DeleteMemberRequ
}
}
+ const force = false
+
var m *model.Member
- m, err = api.app.RemoveMember(ctx, session.Domain(in.GetDomainId()), in.GetQueueId(), in.GetId())
+ m, err = api.app.RemoveMember(ctx, session.Domain(in.GetDomainId()), in.GetQueueId(), in.GetId(), force)
if err != nil {
return nil, err
}
diff --git a/store/sqlstore/cc_member_store.go b/store/sqlstore/cc_member_store.go
index bb310e56..f36c4b2a 100644
--- a/store/sqlstore/cc_member_store.go
+++ b/store/sqlstore/cc_member_store.go
@@ -390,29 +390,18 @@ from m
return member, nil
}
-// TODO add force
-func (s SqlMemberStore) Delete(ctx context.Context, queueId, id int64) model.AppError {
- var cntCheck, cnt int64
-
- check, err := s.GetMaster().WithContext(ctx).Exec(`select 1 from call_center.cc_member_attempt a where a.member_id = :Id and a.state != 'leaving' for update`,
- map[string]interface{}{"Id": id})
- if err != nil {
- return model.NewCustomCodeError("store.sql_member.delete.app_error", fmt.Sprintf("Id=%v, %s", id, err.Error()), extractCodeFromErr(err))
- }
- cntCheck, err = check.RowsAffected()
- if err != nil {
- return model.NewCustomCodeError("store.sql_member.delete.app_error", fmt.Sprintf("Id=%v, %s", id, err.Error()), extractCodeFromErr(err))
- }
-
- if cntCheck == 0 {
- return model.NewCustomCodeError("store.sql_member.delete.app_error", fmt.Sprintf("Id=%v, member reserved", id), http.StatusForbidden)
- }
+func (s SqlMemberStore) Delete(ctx context.Context, queueId, id int64, force bool) model.AppError {
+ var cnt int64
res, err := s.GetMaster().WithContext(ctx).Exec(`delete
from call_center.cc_member c
where c.id = :Id
and c.queue_id = :QueueId
- and not exists(select 1 from call_center.cc_member_attempt a where a.member_id = c.id and a.state != 'leaving' for update)`,
- map[string]interface{}{"Id": id, "QueueId": queueId})
+ and not exists(select 1 from call_center.cc_member_attempt a where not :Force::bool and a.member_id = c.id and a.state != 'leaving' for update)`,
+ map[string]interface{}{
+ "Id": id,
+ "QueueId": queueId,
+ "Force": force,
+ })
if err != nil {
return model.NewCustomCodeError("store.sql_member.delete.app_error", fmt.Sprintf("Id=%v, %s", id, err.Error()), extractCodeFromErr(err))
diff --git a/store/store.go b/store/store.go
index f0c71f17..95038e12 100644
--- a/store/store.go
+++ b/store/store.go
@@ -312,7 +312,7 @@ type MemberStore interface {
SearchMembers(ctx context.Context, domainId int64, search *model.SearchMemberRequest) ([]*model.Member, model.AppError)
Get(ctx context.Context, domainId, queueId, id int64) (*model.Member, model.AppError)
Update(ctx context.Context, domainId int64, member *model.Member) (*model.Member, model.AppError)
- Delete(ctx context.Context, queueId, id int64) model.AppError
+ Delete(ctx context.Context, queueId, id int64, force bool) model.AppError
MultiDelete(ctx context.Context, domainId int64, del *model.MultiDeleteMembers, withoutMembers bool) ([]*model.Member, model.AppError)
ResetMembers(ctx context.Context, domainId int64, req *model.ResetMembers) (int64, model.AppError)