From c3606bc6f6f0df5c4143f618db8e8c4536b1bad4 Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 26 Sep 2026 15:39:10 +0800 Subject: [PATCH] fix(cloudflare): deduplicate batch member ids and guard move dialog dismiss during pending --- .../components/member-move-dialog.tsx | 18 +++++++++++++-- internal/apps/openflare/cloudflare/logics.go | 22 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/frontend/app/(main)/cloudflare/components/member-move-dialog.tsx b/frontend/app/(main)/cloudflare/components/member-move-dialog.tsx index 1d898624..1d2aa8d8 100644 --- a/frontend/app/(main)/cloudflare/components/member-move-dialog.tsx +++ b/frontend/app/(main)/cloudflare/components/member-move-dialog.tsx @@ -70,8 +70,22 @@ export function MemberMoveDialog({ : t('moveDialog.targetGroupLabel'); return ( - - + { + if (!pending) { + onOpenChange(next); + } + }} + > + { + if (pending) e.preventDefault(); + }} + onEscapeKeyDown={(e) => { + if (pending) e.preventDefault(); + }} + > {title} diff --git a/internal/apps/openflare/cloudflare/logics.go b/internal/apps/openflare/cloudflare/logics.go index 848d97bf..d68403f1 100644 --- a/internal/apps/openflare/cloudflare/logics.go +++ b/internal/apps/openflare/cloudflare/logics.go @@ -436,7 +436,7 @@ func BatchMoveMembers(ctx context.Context, sourceGroupID uint, input MemberBatch } return err } - for _, memberID := range input.MemberIDs { + for _, memberID := range uniqueIDs(input.MemberIDs) { member, getErr := repository.GetCFPointingMember(ctx, sourceGroupID, memberID) if getErr != nil { continue @@ -462,7 +462,7 @@ func BatchRemoveMembers(ctx context.Context, sourceGroupID uint, input MemberBat if len(input.MemberIDs) == 0 { return errors.New(errNoMembersSelected) } - for _, memberID := range input.MemberIDs { + for _, memberID := range uniqueIDs(input.MemberIDs) { member, err := repository.GetCFPointingMember(ctx, sourceGroupID, memberID) if err != nil { continue @@ -477,6 +477,24 @@ func BatchRemoveMembers(ctx context.Context, sourceGroupID uint, input MemberBat return nil } +func uniqueIDs(ids []uint) []uint { + if len(ids) == 0 { + return ids + } + seen := make(map[uint]struct{}, len(ids)) + result := make([]uint, 0, len(ids)) + for _, id := range ids { + if id == 0 { + continue + } + if _, exists := seen[id]; !exists { + seen[id] = struct{}{} + result = append(result, id) + } + } + return result +} + // DeleteGroup removes every managed remote A record and then local state. func DeleteGroup(ctx context.Context, groupID uint) error { if _, err := repository.GetCFPointingGroup(ctx, groupID); err != nil {