From af148bafb30878fccd05af44add66e71c1032a4f Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Mon, 24 Nov 2025 12:36:07 +0000 Subject: [PATCH] Merge pull request #28209 from overleaf/mj-dropbox-stop-archived-sync [web] Avoid applying TPDS updates to archived and trashed projects GitOrigin-RevId: c33bfb1ae5975cd98c81b76713fb99369816b188 --- .../ThirdPartyDataStore/TpdsUpdateHandler.mjs | 6 ++- .../TpdsUpdateHandler.test.mjs | 53 +++++++++++++++++-- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.mjs b/services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.mjs index 599db69109..1149ba9939 100644 --- a/services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.mjs +++ b/services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.mjs @@ -107,7 +107,11 @@ async function findProjectByIdWithRWAccess(userId, projectId) { for (const projects of [allProjects.owned, allProjects.readAndWrite]) { for (const project of projects) { if (project._id.toString() === projectId) { - return project + if (ProjectHelper.isArchivedOrTrashed(project, userId)) { + return null + } else { + return project + } } } } diff --git a/services/web/test/unit/src/ThirdPartyDataStore/TpdsUpdateHandler.test.mjs b/services/web/test/unit/src/ThirdPartyDataStore/TpdsUpdateHandler.test.mjs index af771f75f4..eb0a79b4e7 100644 --- a/services/web/test/unit/src/ThirdPartyDataStore/TpdsUpdateHandler.test.mjs +++ b/services/web/test/unit/src/ThirdPartyDataStore/TpdsUpdateHandler.test.mjs @@ -15,6 +15,7 @@ vi.mock('../../../../app/src/Features/Errors/Errors.js', () => describe('TpdsUpdateHandler', function () { beforeEach(async function (ctx) { ctx.projectName = 'My recipes' + ctx.userId = new ObjectId() ctx.projects = { active1: { _id: new ObjectId(), name: ctx.projectName }, active2: { _id: new ObjectId(), name: ctx.projectName }, @@ -28,8 +29,12 @@ describe('TpdsUpdateHandler', function () { name: ctx.projectName, archived: [ctx.userId], }, + trashed: { + _id: new ObjectId(), + name: ctx.projectName, + trashed: [ctx.userId], + }, } - ctx.userId = new ObjectId() ctx.source = 'dropbox' ctx.path = `/some/file` ctx.update = {} @@ -73,9 +78,10 @@ describe('TpdsUpdateHandler', function () { ctx.ProjectGetter = { promises: { findUsersProjectsByName: sinon.stub(), - findAllUsersProjects: sinon - .stub() - .resolves({ owned: [ctx.projects.active1], readAndWrite: [] }), + findAllUsersProjects: sinon.stub().resolves({ + owned: Object.values(ctx.projects), + readAndWrite: [], + }), }, } ctx.ProjectHelper = { @@ -87,6 +93,9 @@ describe('TpdsUpdateHandler', function () { ctx.ProjectHelper.isArchivedOrTrashed .withArgs(ctx.projects.archived2, ctx.userId) .returns(true) + ctx.ProjectHelper.isArchivedOrTrashed + .withArgs(ctx.projects.trashed, ctx.userId) + .returns(true) ctx.RootDocManager = { setRootDocAutomaticallyInBackground: sinon.stub(), } @@ -172,6 +181,24 @@ describe('TpdsUpdateHandler', function () { expectProjectNotCreated() expectUpdateProcessed() }) + + describe('with one matching archived project', function () { + beforeEach(function (ctx) { + ctx.projectId = ctx.projects.archived1._id.toString() + }) + receiveUpdateById() + expectProjectNotCreated() + expectUpdateNotProcessed() + }) + + describe('with one matching trashed project', function () { + beforeEach(function (ctx) { + ctx.projectId = ctx.projects.trashed._id.toString() + }) + receiveUpdateById() + expectProjectNotCreated() + expectUpdateNotProcessed() + }) }) describe('with no matching project', function () { @@ -269,6 +296,24 @@ describe('TpdsUpdateHandler', function () { expectDeleteProcessed() expectProjectNotDeleted() }) + + describe('with one matching archived project', function () { + beforeEach(function (ctx) { + ctx.projectId = ctx.projects.archived1._id.toString() + }) + receiveFileDeleteById() + expectDeleteNotProcessed() + expectProjectNotDeleted() + }) + + describe('with one matching trashed project', function () { + beforeEach(function (ctx) { + ctx.projectId = ctx.projects.trashed._id.toString() + }) + receiveFileDeleteById() + expectDeleteNotProcessed() + expectProjectNotDeleted() + }) }) describe('with no matching project', function () {