Răsfoiți Sursa

[web] update notification preferences on ownership transfer (#33854)

GitOrigin-RevId: c20c7f992d9dbdd6e9f80feafc7b53587c122dd7
Kristina 2 luni în urmă
părinte
comite
dce6bce9fa

+ 16 - 0
services/web/app/src/Features/Collaborators/OwnershipTransferHandler.mjs

@@ -14,6 +14,7 @@ import TagsHandler from '../Tags/TagsHandler.mjs'
 import { promiseMapWithLimit } from '@overleaf/promise-utils'
 import LimitationsManager from '../Subscription/LimitationsManager.mjs'
 import AsyncLocalStorage from '../../infrastructure/AsyncLocalStorage.mjs'
+import Modules from '../../infrastructure/Modules.mjs'
 
 export default {
   promises: {
@@ -142,6 +143,21 @@ async function transferOwnership(projectId, newOwnerId, options = {}) {
     pendingPrivilegeLevel
   )
 
+  // Update notification preferences for both new and previous owner
+  try {
+    await Modules.promises.hooks.fire(
+      'projectOwnershipTransferred',
+      projectId,
+      previousOwnerId,
+      newOwnerId
+    )
+  } catch (err) {
+    logger.error(
+      { err, projectId, previousOwnerId, newOwnerId },
+      'failed to update notification preferences on ownership transfer'
+    )
+  }
+
   // Flush project to TPDS
   await TpdsProjectFlusher.promises.flushProjectToTpds(projectId)
 

+ 24 - 0
services/web/test/unit/src/Collaborators/OwnershipTransferHandler.test.mjs

@@ -85,6 +85,13 @@ describe('OwnershipTransferHandler', function () {
         canAddXEditCollaborators: sinon.stub().resolves(true),
       },
     }
+    ctx.Modules = {
+      promises: {
+        hooks: {
+          fire: sinon.stub().resolves(),
+        },
+      },
+    }
 
     vi.mock('../../../../app/src/Features/Errors/Errors.js', () =>
       vi.importActual('../../../../app/src/Features/Errors/Errors.js')
@@ -148,6 +155,10 @@ describe('OwnershipTransferHandler', function () {
       })
     )
 
+    vi.doMock('../../../../app/src/infrastructure/Modules.mjs', () => ({
+      default: ctx.Modules,
+    }))
+
     ctx.handler = (await import(MODULE_PATH)).default
   })
 
@@ -510,6 +521,19 @@ describe('OwnershipTransferHandler', function () {
       )
     })
 
+    it('should fire the ownershipTransferred hook', async function (ctx) {
+      await ctx.handler.promises.transferOwnership(
+        ctx.project._id,
+        ctx.collaborator._id
+      )
+      expect(ctx.Modules.promises.hooks.fire).to.have.been.calledWith(
+        'projectOwnershipTransferred',
+        ctx.project._id,
+        ctx.user._id,
+        ctx.collaborator._id
+      )
+    })
+
     it('should decline to transfer ownership to a non-collaborator', async function (ctx) {
       ctx.project.collaberator_refs = []
       ctx.project.readOnly_refs = []