From f2bdd1645d9c80a310ce621babe1bd0e4ad07840 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Wed, 3 Jun 2026 10:20:58 -0400 Subject: [PATCH] fix: Preserve Private Legacy Shared Links --- .../migrate-shared-link-permissions.spec.js | 21 ++++++++ config/migrate-shared-link-permissions.js | 50 +++++++++---------- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/config/__tests__/migrate-shared-link-permissions.spec.js b/config/__tests__/migrate-shared-link-permissions.spec.js index ebc6183803..856795b6a1 100644 --- a/config/__tests__/migrate-shared-link-permissions.spec.js +++ b/config/__tests__/migrate-shared-link-permissions.spec.js @@ -146,4 +146,25 @@ describe('migrate-shared-link-permissions', () => { expect(raw1).toHaveProperty('isPublic', true); expect(raw2).toHaveProperty('isPublic', true); }); + + test('does not grant PUBLIC VIEWER to isPublic false links when forced', async () => { + const link = await createLegacyLink(false); + + const result = await migrateSharedLinkPermissions({ dryRun: false, force: true }); + + expect(result.aborted).toBeUndefined(); + expect(result.publicViewerSkipped).toBe(1); + + const publicEntry = await AclEntry.findOne({ + resourceId: link._id, + principalType: 'public', + }).lean(); + expect(publicEntry).toBeNull(); + + const ownerEntry = await AclEntry.findOne({ + resourceId: link._id, + principalType: 'user', + }).lean(); + expect(ownerEntry).toBeDefined(); + }); }); diff --git a/config/migrate-shared-link-permissions.js b/config/migrate-shared-link-permissions.js index 219d9e91e6..5d49a2cc77 100644 --- a/config/migrate-shared-link-permissions.js +++ b/config/migrate-shared-link-permissions.js @@ -189,33 +189,31 @@ async function migrateSharedLinkPermissions({ } const hasIsPublic = link.isPublic !== undefined; - if (hasIsPublic) { - if (link.isPublic === false && !force) { - results.publicViewerSkipped++; - } else { - opIndexToLinkId.push(linkId); - bulkOps.push({ - updateOne: { - filter: { - resourceType: RESOURCE_TYPE_SHARED_LINK, - resourceId: linkId, - principalType: PRINCIPAL_PUBLIC, - }, - update: { - $set: { - permBits: viewerRole.permBits, - roleId: viewerRole._id, - grantedBy: userId ? new mongoose.Types.ObjectId(userId) : undefined, - grantedAt: now, - }, - $setOnInsert: { - ...(tenantId && { tenantId }), - }, - }, - upsert: true, + if (hasIsPublic && link.isPublic === false) { + results.publicViewerSkipped++; + } else if (hasIsPublic) { + opIndexToLinkId.push(linkId); + bulkOps.push({ + updateOne: { + filter: { + resourceType: RESOURCE_TYPE_SHARED_LINK, + resourceId: linkId, + principalType: PRINCIPAL_PUBLIC, }, - }); - } + update: { + $set: { + permBits: viewerRole.permBits, + roleId: viewerRole._id, + grantedBy: userId ? new mongoose.Types.ObjectId(userId) : undefined, + grantedAt: now, + }, + $setOnInsert: { + ...(tenantId && { tenantId }), + }, + }, + upsert: true, + }, + }); } results.migrated++;