Skip to content

fix(cozy-sharing): Accumulate recipients in federated folder sharing#2961

Merged
doubleface merged 3 commits intomasterfrom
fix/accumulateSharingRecipients
Mar 23, 2026
Merged

fix(cozy-sharing): Accumulate recipients in federated folder sharing#2961
doubleface merged 3 commits intomasterfrom
fix/accumulateSharingRecipients

Conversation

@doubleface
Copy link
Contributor

@doubleface doubleface commented Mar 19, 2026

When the drive.federated-shared-folder.enable flag is active, each recipient added via onShare was overwriting the previous ones. Use mergeAndDeduplicateRecipients to properly accumulate recipients, matching the behavior of SharedDriveModal.

https://www.notion.so/linagora/Drive-Board-20062718bad180d687d1f517b2ed7dda?p=32062718bad180fdbd6ad1f8915b52d3&pm=s&pvs=31

Summary by CodeRabbit

  • Bug Fixes

    • Sharing now accumulates recipients across multiple share actions, correctly merging and deduplicating read-only and read-write recipients (normalizing id/_id values to prevent duplicates).
  • Tests

    • Added tests for recipient merge/deduplication, id/_id normalization, moving recipients between access modes, formatting/sorting output, and UI accumulation after repeated shares.

@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

Caution

Review failed

The head commit changed during the review from 578c3e0 to 93696b4.

Walkthrough

The PR updates FederatedFolderModal to use a functional state updater for federatedRecipients, appending incoming params.recipients and params.readOnlyRecipients to existing arrays and de-duplicating them via the new mergeAndDeduplicateRecipients helper (which normalizes id/_id into id). Tests were added/updated: a new test suite for SharedDrive helpers (including mergeAndDeduplicateRecipients, moveRecipientToReadWrite, moveRecipientToReadOnly, formatRecipients) and FederatedFolderModal specs confirming recipients accumulate across multiple onShare calls and mock share payloads include id fields.

Possibly related PRs

Suggested reviewers

  • JF-Cozy
  • rezk2ll
  • zatteo
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing recipient accumulation in federated folder sharing instead of overwriting recipients.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/accumulateSharingRecipients

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/cozy-sharing/src/components/FederatedFolder/FederatedFolderModal.spec.jsx (1)

65-75: Add a duplicate-recipient assertion so deduplication is actually tested.

Line 241 currently shares only a new recipient, so this test proves accumulation but not deduplication. Include one already-shared recipient in the second onShare payload and keep expected total at 3 to cover the dedupe path.

Suggested test adjustment
       <button
         data-testid="btn-share-other"
         onClick={() =>
           onShare({
-            recipients: [{ _id: 'r3', id: 'r3', displayName: 'Charlie' }],
+            recipients: [
+              { _id: 'r1', id: 'r1', displayName: 'Alice' }, // duplicate
+              { _id: 'r3', id: 'r3', displayName: 'Charlie' } // new
+            ],
             readOnlyRecipients: []
           })
         }
       >

Also applies to: 228-246

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/cozy-sharing/src/components/FederatedFolder/FederatedFolderModal.spec.jsx`
around lines 65 - 75, The second simulated share in the test currently only adds
a new recipient so deduplication isn't exercised; update the onShare payload
invoked by the button with data-testid "btn-share-other" to include one
recipient already present in the initial share (use the same _id/id value used
in the first onShare) along with the new recipient, then keep the assertion
expecting total recipients to be 3 so the test verifies deduplication logic in
the FederatedFolderModal component.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/cozy-sharing/src/components/FederatedFolder/FederatedFolderModal.jsx`:
- Around line 70-79: The merge/deduplicate call is losing recipients because
mergeAndDeduplicateRecipients dedups by item.id while this modal sometimes uses
_id; before calling setFederatedRecipients/mergeAndDeduplicateRecipients (in the
setFederatedRecipients block that handles params.recipients and
params.readOnlyRecipients) normalize each recipient to ensure an id property
exists (e.g., map recipients -> ({ ...r, id: r.id || r._id })) for both incoming
params arrays and previous recipients, avoid mutating originals by returning new
objects, then pass those normalized arrays into mergeAndDeduplicateRecipients so
deduplication uses a consistent id field.

---

Nitpick comments:
In
`@packages/cozy-sharing/src/components/FederatedFolder/FederatedFolderModal.spec.jsx`:
- Around line 65-75: The second simulated share in the test currently only adds
a new recipient so deduplication isn't exercised; update the onShare payload
invoked by the button with data-testid "btn-share-other" to include one
recipient already present in the initial share (use the same _id/id value used
in the first onShare) along with the new recipient, then keep the assertion
expecting total recipients to be 3 so the test verifies deduplication logic in
the FederatedFolderModal component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a913e246-de8b-4510-9aba-50a66ccfc863

📥 Commits

Reviewing files that changed from the base of the PR and between 71eb651 and c65cb77.

📒 Files selected for processing (2)
  • packages/cozy-sharing/src/components/FederatedFolder/FederatedFolderModal.jsx
  • packages/cozy-sharing/src/components/FederatedFolder/FederatedFolderModal.spec.jsx

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cozy-sharing/src/components/SharedDrive/helpers.js (1)

15-21: ⚠️ Potential issue | 🟡 Minor

Avoid dropping multiple recipients when id is missing.

At Line 16, recipients with no id/_id all collapse under the same undefined key, so only the first one is kept.

💡 Suggested hardening
 const uniqueArray = combinedArray.filter(item => {
-  if (!seenIds.has(item.id)) {
-    seenIds.add(item.id)
-    return true
-  }
-  return false
+  if (item.id == null) return true
+  if (seenIds.has(item.id)) return false
+  seenIds.add(item.id)
+  return true
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cozy-sharing/src/components/SharedDrive/helpers.js` around lines 15
- 21, The current dedupe logic in the uniqueArray filter collapses recipients
lacking item.id into a single undefined key via seenIds, dropping all but the
first; update the filter to compute a stable dedupe key (e.g., const key =
item.id || item._id || some other unique property like item.email ||
JSON.stringify(item)) and use that key with seenIds (check seenIds.has(key) and
seenIds.add(key)) instead of item.id directly so recipients without id/_id are
deduplicated correctly.
🧹 Nitpick comments (1)
packages/cozy-sharing/src/components/SharedDrive/helpers.spec.js (1)

111-163: Optional: add a formatter fallback test for name when displayName is absent.

formatRecipients has a fallback path (displayName || name) that isn’t explicitly asserted yet; a small test would prevent regressions there.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cozy-sharing/src/components/SharedDrive/helpers.spec.js` around
lines 111 - 163, Add a new unit test for formatRecipients that verifies the
fallback to the name field when displayName is missing: create input where a
recipient object has no displayName but has name (and an email/ _id), call
formatRecipients, and assert the returned item's public_name equals the original
name; also assert index uses RECIPIENT_INDEX_PREFIX + _id and that readOnly vs
recipients map to types ('two-way'/'one-way') as in existing tests to prevent
regressions in the fallback path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/cozy-sharing/src/components/SharedDrive/helpers.js`:
- Around line 15-21: The current dedupe logic in the uniqueArray filter
collapses recipients lacking item.id into a single undefined key via seenIds,
dropping all but the first; update the filter to compute a stable dedupe key
(e.g., const key = item.id || item._id || some other unique property like
item.email || JSON.stringify(item)) and use that key with seenIds (check
seenIds.has(key) and seenIds.add(key)) instead of item.id directly so recipients
without id/_id are deduplicated correctly.

---

Nitpick comments:
In `@packages/cozy-sharing/src/components/SharedDrive/helpers.spec.js`:
- Around line 111-163: Add a new unit test for formatRecipients that verifies
the fallback to the name field when displayName is missing: create input where a
recipient object has no displayName but has name (and an email/ _id), call
formatRecipients, and assert the returned item's public_name equals the original
name; also assert index uses RECIPIENT_INDEX_PREFIX + _id and that readOnly vs
recipients map to types ('two-way'/'one-way') as in existing tests to prevent
regressions in the fallback path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b05dbae6-9746-47b5-8155-5e6592cf3396

📥 Commits

Reviewing files that changed from the base of the PR and between c65cb77 and d158098.

📒 Files selected for processing (2)
  • packages/cozy-sharing/src/components/SharedDrive/helpers.js
  • packages/cozy-sharing/src/components/SharedDrive/helpers.spec.js

When the drive.federated-shared-folder.enable flag is active, each recipient
added via onShare was overwriting the previous ones. Use mergeAndDeduplicateRecipients
to properly accumulate recipients, matching the behavior of SharedDriveModal.
@doubleface doubleface force-pushed the fix/accumulateSharingRecipients branch 2 times, most recently from 6182960 to 29bbbdf Compare March 20, 2026 08:30
Copy link
Member

@rezk2ll rezk2ll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_id-only code paths downstream. The rest of the helpers (moveRecipientToReadWrite, moveRecipientToReadOnly, formatRecipients) and onRevoke in FederatedFolderModal all match by r._id. This works today because recipients always arrive with _id (cozy-client guarantees it), but the normalization is asymmetric: it ensures id exists, not _id. If a recipient ever arrives with only id, the move/revoke/format functions silently fail. Low risk in practice, but the inconsistency is worth being aware of.

Recipients without any identifier. If a recipient has neither id nor _id, the normalized id is undefined. Multiple such recipients collapse into one because Set treats all undefined keys as equal. Unlikely in production, but the dedup silently drops data without warning. CodeRabbit flagged this too.

Added id/_id normalization into mergeAndDeduplicateRecipients
to have correct deduplication of recipients
Added unit tests for SharedDrive helpers.
@doubleface doubleface force-pushed the fix/accumulateSharingRecipients branch from 29bbbdf to 578c3e0 Compare March 23, 2026 09:41
@doubleface doubleface merged commit 6bd9292 into master Mar 23, 2026
2 checks passed
@doubleface doubleface deleted the fix/accumulateSharingRecipients branch March 23, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants