Просмотр исходного кода

Merge pull request #6453 from weseek/feat/descendant-notifications-delete/deleteCompletely

feat: Feat/descendant notifications delete/delete completely/revert
Yuki Takei 3 лет назад
Родитель
Сommit
722b3a98a1

+ 2 - 2
packages/app/src/server/routes/index.js

@@ -172,8 +172,8 @@ module.exports = function(crowi, app) {
   apiV1Router.get('/pages.updatePost'    , accessTokenParser, loginRequired, page.api.getUpdatePost);
   apiV1Router.get('/pages.updatePost'    , accessTokenParser, loginRequired, page.api.getUpdatePost);
   apiV1Router.get('/pages.getPageTag'    , accessTokenParser , loginRequired , page.api.getPageTag);
   apiV1Router.get('/pages.getPageTag'    , accessTokenParser , loginRequired , page.api.getPageTag);
   // allow posting to guests because the client doesn't know whether the user logged in
   // allow posting to guests because the client doesn't know whether the user logged in
-  apiV1Router.post('/pages.remove'       , loginRequiredStrictly , csrf, addActivity, page.validator.remove, apiV1FormValidator, page.api.remove); // (Avoid from API Token)
-  apiV1Router.post('/pages.revertRemove' , loginRequiredStrictly , csrf, addActivity, page.validator.revertRemove, apiV1FormValidator, page.api.revertRemove); // (Avoid from API Token)
+  apiV1Router.post('/pages.remove'       , loginRequiredStrictly , csrf, page.validator.remove, apiV1FormValidator, page.api.remove); // (Avoid from API Token)
+  apiV1Router.post('/pages.revertRemove' , loginRequiredStrictly , csrf, page.validator.revertRemove, apiV1FormValidator, page.api.revertRemove); // (Avoid from API Token)
   apiV1Router.post('/pages.unlink'       , loginRequiredStrictly , csrf, page.api.unlink); // (Avoid from API Token)
   apiV1Router.post('/pages.unlink'       , loginRequiredStrictly , csrf, page.api.unlink); // (Avoid from API Token)
   apiV1Router.post('/pages.duplicate'    , accessTokenParser, loginRequiredStrictly, csrf, page.api.duplicate);
   apiV1Router.post('/pages.duplicate'    , accessTokenParser, loginRequiredStrictly, csrf, page.api.duplicate);
   apiV1Router.get('/tags.list'           , accessTokenParser, loginRequired, tag.api.list);
   apiV1Router.get('/tags.list'           , accessTokenParser, loginRequired, tag.api.list);

+ 13 - 29
packages/app/src/server/routes/page.js

@@ -1270,6 +1270,11 @@ module.exports = function(crowi, app) {
 
 
     const options = {};
     const options = {};
 
 
+    const activityParameters = {
+      ip: req.ip,
+      endpoint: req.originalUrl,
+    };
+
     const page = await Page.findByIdAndViewer(pageId, req.user, null, true);
     const page = await Page.findByIdAndViewer(pageId, req.user, null, true);
 
 
     if (page == null) {
     if (page == null) {
@@ -1288,23 +1293,15 @@ module.exports = function(crowi, app) {
 
 
     debug('Delete page', page._id, page.path);
     debug('Delete page', page._id, page.path);
 
 
-    let deleteAction;
-    let descendantPages;
-
     try {
     try {
-      const pages = await Page.findListWithDescendants(page.path, req.user);
-      descendantPages = pages.pages;
-      descendantPages.pop();
       if (isCompletely) {
       if (isCompletely) {
         if (!crowi.pageService.canDeleteCompletely(page.path, creator, req.user, isRecursively)) {
         if (!crowi.pageService.canDeleteCompletely(page.path, creator, req.user, isRecursively)) {
           return res.json(ApiResponse.error('You can not delete this page completely', 'user_not_admin'));
           return res.json(ApiResponse.error('You can not delete this page completely', 'user_not_admin'));
         }
         }
-        deleteAction = isRecursively ? SupportedAction.ACTION_PAGE_RECURSIVELY_DELETE_COMPLETELY : SupportedAction.ACTION_PAGE_DELETE_COMPLETELY;
-        await crowi.pageService.deleteCompletely(page, req.user, options, isRecursively);
+        await crowi.pageService.deleteCompletely(page, req.user, options, isRecursively, activityParameters);
       }
       }
       else {
       else {
         // behave like not found
         // behave like not found
-        deleteAction = isRecursively ? SupportedAction.ACTION_PAGE_RECURSIVELY_DELETE : SupportedAction.ACTION_PAGE_DELETE;
         const notRecursivelyAndEmpty = page.isEmpty && !isRecursively;
         const notRecursivelyAndEmpty = page.isEmpty && !isRecursively;
         if (notRecursivelyAndEmpty) {
         if (notRecursivelyAndEmpty) {
           return res.json(ApiResponse.error(`Page '${pageId}' is not found.`, 'notfound'));
           return res.json(ApiResponse.error(`Page '${pageId}' is not found.`, 'notfound'));
@@ -1318,7 +1315,7 @@ module.exports = function(crowi, app) {
           return res.json(ApiResponse.error('You can not delete this page', 'user_not_admin'));
           return res.json(ApiResponse.error('You can not delete this page', 'user_not_admin'));
         }
         }
 
 
-        await crowi.pageService.deletePage(page, req.user, options, isRecursively);
+        await crowi.pageService.deletePage(page, req.user, options, isRecursively, activityParameters);
       }
       }
     }
     }
     catch (err) {
     catch (err) {
@@ -1332,14 +1329,6 @@ module.exports = function(crowi, app) {
     result.isRecursively = isRecursively;
     result.isRecursively = isRecursively;
     result.isCompletely = isCompletely;
     result.isCompletely = isCompletely;
 
 
-    const parameters = {
-      targetModel: SupportedTargetModel.MODEL_PAGE,
-      target: page,
-      action: deleteAction,
-    };
-
-    activityEvent.emit('update', res.locals.activity._id, parameters, page, descendantPages);
-
     res.json(ApiResponse.success(result));
     res.json(ApiResponse.success(result));
 
 
     try {
     try {
@@ -1371,6 +1360,11 @@ module.exports = function(crowi, app) {
     // get recursively flag
     // get recursively flag
     const isRecursively = req.body.recursively;
     const isRecursively = req.body.recursively;
 
 
+    const activityParameters = {
+      ip: req.ip,
+      endpoint: req.originalUrl,
+    };
+
     let page;
     let page;
     let descendantPages;
     let descendantPages;
     try {
     try {
@@ -1378,10 +1372,7 @@ module.exports = function(crowi, app) {
       if (page == null) {
       if (page == null) {
         throw new Error(`Page '${pageId}' is not found or forbidden`, 'notfound_or_forbidden');
         throw new Error(`Page '${pageId}' is not found or forbidden`, 'notfound_or_forbidden');
       }
       }
-      page = await crowi.pageService.revertDeletedPage(page, req.user, {}, isRecursively);
-      const pages = await Page.findListWithDescendants(page.path, req.user);
-      descendantPages = pages.pages;
-      descendantPages.pop();
+      page = await crowi.pageService.revertDeletedPage(page, req.user, {}, isRecursively, activityParameters);
     }
     }
     catch (err) {
     catch (err) {
       if (err instanceof PathAlreadyExistsError) {
       if (err instanceof PathAlreadyExistsError) {
@@ -1395,13 +1386,6 @@ module.exports = function(crowi, app) {
     const result = {};
     const result = {};
     result.page = page; // TODO consider to use serializePageSecurely method -- 2018.08.06 Yuki Takei
     result.page = page; // TODO consider to use serializePageSecurely method -- 2018.08.06 Yuki Takei
 
 
-    const parameters = {
-      targetModel: SupportedTargetModel.MODEL_PAGE,
-      target: page,
-      action: isRecursively ? SupportedAction.ACTION_PAGE_RECURSIVELY_REVERT : SupportedAction.ACTION_PAGE_REVERT,
-    };
-    activityEvent.emit('update', res.locals.activity._id, parameters, page, descendantPages);
-
     return res.json(ApiResponse.success(result));
     return res.json(ApiResponse.success(result));
   };
   };
 
 

+ 80 - 15
packages/app/src/server/service/page.ts

@@ -1359,7 +1359,7 @@ class PageService {
   /*
   /*
    * Delete
    * Delete
    */
    */
-  async deletePage(page, user, options = {}, isRecursively = false) {
+  async deletePage(page, user, options = {}, isRecursively = false, activityParameters?) {
     /*
     /*
      * Common Operation
      * Common Operation
      */
      */
@@ -1397,6 +1397,18 @@ class PageService {
       await Page.replaceTargetWithPage(page, null, true);
       await Page.replaceTargetWithPage(page, null, true);
     }
     }
 
 
+    const parameters = {
+      ip: activityParameters.ip,
+      endpoint: activityParameters.endpoint,
+      action: page.descendantCount > 0 ? SupportedAction.ACTION_PAGE_RECURSIVELY_DELETE : SupportedAction.ACTION_PAGE_DELETE,
+      user,
+      snapshot: {
+        username: user.username,
+      },
+    };
+
+    const activity = await this.crowi.activityService.createActivity(parameters);
+
     // Delete target (only updating an existing document's properties )
     // Delete target (only updating an existing document's properties )
     let deletedPage;
     let deletedPage;
     if (!page.isEmpty) {
     if (!page.isEmpty) {
@@ -1440,7 +1452,7 @@ class PageService {
        */
        */
       (async() => {
       (async() => {
         try {
         try {
-          await this.deleteRecursivelyMainOperation(page, user, pageOp._id);
+          await this.deleteRecursivelyMainOperation(page, user, pageOp._id, activity);
         }
         }
         catch (err) {
         catch (err) {
           logger.error('Error occurred while running deleteRecursivelyMainOperation.', err);
           logger.error('Error occurred while running deleteRecursivelyMainOperation.', err);
@@ -1452,6 +1464,9 @@ class PageService {
         }
         }
       })();
       })();
     }
     }
+    else {
+      this.activityEvent.emit('updated', activity, page);
+    }
 
 
     return deletedPage;
     return deletedPage;
   }
   }
@@ -1483,8 +1498,12 @@ class PageService {
     return deletedPage;
     return deletedPage;
   }
   }
 
 
-  async deleteRecursivelyMainOperation(page, user, pageOpId: ObjectIdLike): Promise<void> {
-    await this.deleteDescendantsWithStream(page, user, false);
+  async deleteRecursivelyMainOperation(page, user, pageOpId: ObjectIdLike, activity?): Promise<void> {
+    const descendantsSubscribedSets = new Set();
+    await this.deleteDescendantsWithStream(page, user, false, descendantsSubscribedSets);
+
+    const descendantsSubscribedUsers = Array.from(descendantsSubscribedSets);
+    this.activityEvent.emit('updated', activity, page, descendantsSubscribedUsers);
 
 
     await PageOperation.findByIdAndDelete(pageOpId);
     await PageOperation.findByIdAndDelete(pageOpId);
 
 
@@ -1606,7 +1625,7 @@ class PageService {
   /**
   /**
    * Create delete stream and return deleted document count
    * Create delete stream and return deleted document count
    */
    */
-  private async deleteDescendantsWithStream(targetPage, user, shouldUseV4Process = true): Promise<number> {
+  private async deleteDescendantsWithStream(targetPage, user, shouldUseV4Process = true, descendantsSubscribedSets?): Promise<number> {
     let readStream;
     let readStream;
     if (shouldUseV4Process) {
     if (shouldUseV4Process) {
       readStream = await this.generateReadStreamToOperateOnlyDescendants(targetPage.path, user);
       readStream = await this.generateReadStreamToOperateOnlyDescendants(targetPage.path, user);
@@ -1629,6 +1648,10 @@ class PageService {
         try {
         try {
           count += batch.length;
           count += batch.length;
           await deleteDescendants(batch, user);
           await deleteDescendants(batch, user);
+          const subscribedUsers = await Subscription.getSubscriptions(batch);
+          subscribedUsers.forEach((eachUser) => {
+            descendantsSubscribedSets.add(eachUser);
+          });
           logger.debug(`Deleting pages progressing: (count=${count})`);
           logger.debug(`Deleting pages progressing: (count=${count})`);
         }
         }
         catch (err) {
         catch (err) {
@@ -1693,7 +1716,7 @@ class PageService {
     return;
     return;
   }
   }
 
 
-  async deleteCompletely(page, user, options = {}, isRecursively = false, preventEmitting = false) {
+  async deleteCompletely(page, user, options = {}, isRecursively = false, preventEmitting = false, activityParameters?) {
     /*
     /*
      * Common Operation
      * Common Operation
      */
      */
@@ -1723,6 +1746,18 @@ class PageService {
 
 
     logger.debug('Deleting completely', paths);
     logger.debug('Deleting completely', paths);
 
 
+    const parameters = {
+      ip: activityParameters.ip,
+      endpoint: activityParameters.endpoint,
+      action: page.descendantCount > 0 ? SupportedAction.ACTION_PAGE_RECURSIVELY_DELETE_COMPLETELY : SupportedAction.ACTION_PAGE_DELETE_COMPLETELY,
+      user,
+      snapshot: {
+        username: user.username,
+      },
+    };
+
+    const activity = await this.crowi.activityService.createActivity(parameters);
+
     // 1. update descendantCount
     // 1. update descendantCount
     if (isRecursively) {
     if (isRecursively) {
       const inc = page.isEmpty ? -page.descendantCount : -(page.descendantCount + 1);
       const inc = page.isEmpty ? -page.descendantCount : -(page.descendantCount + 1);
@@ -1768,7 +1803,7 @@ class PageService {
        */
        */
       (async() => {
       (async() => {
         try {
         try {
-          await this.deleteCompletelyRecursivelyMainOperation(page, user, options, pageOp._id);
+          await this.deleteCompletelyRecursivelyMainOperation(page, user, options, pageOp._id, activity);
         }
         }
         catch (err) {
         catch (err) {
           logger.error('Error occurred while running deleteCompletelyRecursivelyMainOperation.', err);
           logger.error('Error occurred while running deleteCompletelyRecursivelyMainOperation.', err);
@@ -1780,12 +1815,18 @@ class PageService {
         }
         }
       })();
       })();
     }
     }
+    else {
+      this.activityEvent.emit('updated', activity, page);
+    }
 
 
     return;
     return;
   }
   }
 
 
-  async deleteCompletelyRecursivelyMainOperation(page, user, options, pageOpId: ObjectIdLike): Promise<void> {
-    await this.deleteCompletelyDescendantsWithStream(page, user, options, false);
+  async deleteCompletelyRecursivelyMainOperation(page, user, options, pageOpId: ObjectIdLike, activity?): Promise<void> {
+    const descendantsSubscribedSets = new Set();
+    await this.deleteCompletelyDescendantsWithStream(page, user, options, false, descendantsSubscribedSets);
+    const descendantsSubscribedUsers = Array.from(descendantsSubscribedSets);
+    this.activityEvent.emit('updated', activity, page, descendantsSubscribedUsers);
 
 
     await PageOperation.findByIdAndDelete(pageOpId);
     await PageOperation.findByIdAndDelete(pageOpId);
 
 
@@ -1818,7 +1859,7 @@ class PageService {
   /**
   /**
    * Create delete completely stream
    * Create delete completely stream
    */
    */
-  private async deleteCompletelyDescendantsWithStream(targetPage, user, options = {}, shouldUseV4Process = true): Promise<number> {
+  private async deleteCompletelyDescendantsWithStream(targetPage, user, options = {}, shouldUseV4Process = true, descendantsSubscribedSets?): Promise<number> {
     let readStream;
     let readStream;
 
 
     if (shouldUseV4Process) { // pages don't have parents
     if (shouldUseV4Process) { // pages don't have parents
@@ -1841,6 +1882,10 @@ class PageService {
         try {
         try {
           count += batch.length;
           count += batch.length;
           await deleteMultipleCompletely(batch, user, options);
           await deleteMultipleCompletely(batch, user, options);
+          const subscribedUsers = await Subscription.getSubscriptions(batch);
+          subscribedUsers.forEach((eachUser) => {
+            descendantsSubscribedSets.add(eachUser);
+          });
           logger.debug(`Adding pages progressing: (count=${count})`);
           logger.debug(`Adding pages progressing: (count=${count})`);
         }
         }
         catch (err) {
         catch (err) {
@@ -1924,13 +1969,25 @@ class PageService {
     }
     }
   }
   }
 
 
-  async revertDeletedPage(page, user, options = {}, isRecursively = false) {
+  async revertDeletedPage(page, user, options = {}, isRecursively = false, activityParameters?) {
     /*
     /*
      * Common Operation
      * Common Operation
      */
      */
     const Page = this.crowi.model('Page');
     const Page = this.crowi.model('Page');
     const PageTagRelation = this.crowi.model('PageTagRelation');
     const PageTagRelation = this.crowi.model('PageTagRelation');
 
 
+    const parameters = {
+      ip: activityParameters.ip,
+      endpoint: activityParameters.endpoint,
+      action: page.descendantCount > 0 ? SupportedAction.ACTION_PAGE_RECURSIVELY_REVERT : SupportedAction.ACTION_PAGE_REVERT,
+      user,
+      snapshot: {
+        username: user.username,
+      },
+    };
+
+    const activity = await this.crowi.activityService.createActivity(parameters);
+
     // 1. Separate v4 & v5 process
     // 1. Separate v4 & v5 process
     const shouldUseV4Process = this.shouldUseV4ProcessForRevert(page);
     const shouldUseV4Process = this.shouldUseV4ProcessForRevert(page);
     if (shouldUseV4Process) {
     if (shouldUseV4Process) {
@@ -1965,6 +2022,7 @@ class PageService {
 
 
     if (!isRecursively) {
     if (!isRecursively) {
       await this.updateDescendantCountOfAncestors(parent._id, 1, true);
       await this.updateDescendantCountOfAncestors(parent._id, 1, true);
+      this.activityEvent.emit('updated', activity, page);
     }
     }
     else {
     else {
       let pageOp;
       let pageOp;
@@ -1988,7 +2046,7 @@ class PageService {
        */
        */
       (async() => {
       (async() => {
         try {
         try {
-          await this.revertRecursivelyMainOperation(page, user, options, pageOp._id);
+          await this.revertRecursivelyMainOperation(page, user, options, pageOp._id, activity);
         }
         }
         catch (err) {
         catch (err) {
           logger.error('Error occurred while running revertRecursivelyMainOperation.', err);
           logger.error('Error occurred while running revertRecursivelyMainOperation.', err);
@@ -2004,10 +2062,13 @@ class PageService {
     return updatedPage;
     return updatedPage;
   }
   }
 
 
-  async revertRecursivelyMainOperation(page, user, options, pageOpId: ObjectIdLike): Promise<void> {
+  async revertRecursivelyMainOperation(page, user, options, pageOpId: ObjectIdLike, activity?): Promise<void> {
     const Page = mongoose.model('Page') as unknown as PageModel;
     const Page = mongoose.model('Page') as unknown as PageModel;
 
 
-    await this.revertDeletedDescendantsWithStream(page, user, options, false);
+    const descendantsSubscribedSets = new Set();
+    await this.revertDeletedDescendantsWithStream(page, user, options, false, descendantsSubscribedSets);
+    const descendantsSubscribedUsers = Array.from(descendantsSubscribedSets);
+    this.activityEvent.emit('updated', activity, page, descendantsSubscribedUsers);
 
 
     const newPath = Page.getRevertDeletedPageName(page.path);
     const newPath = Page.getRevertDeletedPageName(page.path);
     // normalize parent of descendant pages
     // normalize parent of descendant pages
@@ -2082,7 +2143,7 @@ class PageService {
   /**
   /**
    * Create revert stream
    * Create revert stream
    */
    */
-  private async revertDeletedDescendantsWithStream(targetPage, user, options = {}, shouldUseV4Process = true): Promise<number> {
+  private async revertDeletedDescendantsWithStream(targetPage, user, options = {}, shouldUseV4Process = true, descendantsSubscribedSets?): Promise<number> {
     if (shouldUseV4Process) {
     if (shouldUseV4Process) {
       return this.revertDeletedDescendantsWithStreamV4(targetPage, user, options);
       return this.revertDeletedDescendantsWithStreamV4(targetPage, user, options);
     }
     }
@@ -2097,6 +2158,10 @@ class PageService {
         try {
         try {
           count += batch.length;
           count += batch.length;
           await revertDeletedDescendants(batch, user);
           await revertDeletedDescendants(batch, user);
+          const subscribedUsers = await Subscription.getSubscriptions(batch);
+          subscribedUsers.forEach((eachUser) => {
+            descendantsSubscribedSets.add(eachUser);
+          });
           logger.debug(`Reverting pages progressing: (count=${count})`);
           logger.debug(`Reverting pages progressing: (count=${count})`);
         }
         }
         catch (err) {
         catch (err) {

+ 31 - 13
packages/app/test/integration/service/page.test.js

@@ -387,7 +387,7 @@ describe('PageService', () => {
   describe('rename page without using renameDescendantsWithStreamSpy', () => {
   describe('rename page without using renameDescendantsWithStreamSpy', () => {
     test('rename page with different tree with isRecursively [deeper]', async() => {
     test('rename page with different tree with isRecursively [deeper]', async() => {
       const resultPage = await crowi.pageService.renamePage(parentForRename6, '/parentForRename6/renamedChild', testUser1, { isRecursively: true },
       const resultPage = await crowi.pageService.renamePage(parentForRename6, '/parentForRename6/renamedChild', testUser1, { isRecursively: true },
-        { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename', activityId: '62e291bc10e0ab61bd691794' });
+        { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename' });
       const wrongPage = await Page.findOne({ path: '/parentForRename6/renamedChild/renamedChild' });
       const wrongPage = await Page.findOne({ path: '/parentForRename6/renamedChild/renamedChild' });
       const expectPage1 = await Page.findOne({ path: '/parentForRename6/renamedChild' });
       const expectPage1 = await Page.findOne({ path: '/parentForRename6/renamedChild' });
       const expectPage2 = await Page.findOne({ path: '/parentForRename6-2021H1' });
       const expectPage2 = await Page.findOne({ path: '/parentForRename6-2021H1' });
@@ -410,7 +410,7 @@ describe('PageService', () => {
       // when
       // when
       //   rename /level1/level2 --> /level1
       //   rename /level1/level2 --> /level1
       await crowi.pageService.renamePage(parentForRename7, '/level1', testUser1, { isRecursively: true },
       await crowi.pageService.renamePage(parentForRename7, '/level1', testUser1, { isRecursively: true },
-        { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename', activityId: '62e291bc10e0ab61bd691794' });
+        { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename' });
 
 
       // then
       // then
       expect(await Page.findOne({ path: '/level1' })).not.toBeNull();
       expect(await Page.findOne({ path: '/level1' })).not.toBeNull();
@@ -441,7 +441,7 @@ describe('PageService', () => {
       test('rename page without options', async() => {
       test('rename page without options', async() => {
 
 
         const resultPage = await crowi.pageService.renamePage(parentForRename1,
         const resultPage = await crowi.pageService.renamePage(parentForRename1,
-          '/renamed1', testUser2, {}, { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename', activityId: '62e291bc10e0ab61bd691794' });
+          '/renamed1', testUser2, {}, { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename' });
 
 
         expect(xssSpy).toHaveBeenCalled();
         expect(xssSpy).toHaveBeenCalled();
 
 
@@ -455,7 +455,7 @@ describe('PageService', () => {
       test('rename page with updateMetadata option', async() => {
       test('rename page with updateMetadata option', async() => {
 
 
         const resultPage = await crowi.pageService.renamePage(parentForRename2, '/renamed2', testUser2, { updateMetadata: true },
         const resultPage = await crowi.pageService.renamePage(parentForRename2, '/renamed2', testUser2, { updateMetadata: true },
-          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename', activityId: '62e291bc10e0ab61bd691794' });
+          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename' });
 
 
         expect(xssSpy).toHaveBeenCalled();
         expect(xssSpy).toHaveBeenCalled();
 
 
@@ -469,7 +469,7 @@ describe('PageService', () => {
       test('rename page with createRedirectPage option', async() => {
       test('rename page with createRedirectPage option', async() => {
 
 
         const resultPage = await crowi.pageService.renamePage(parentForRename3, '/renamed3', testUser2, { createRedirectPage: true },
         const resultPage = await crowi.pageService.renamePage(parentForRename3, '/renamed3', testUser2, { createRedirectPage: true },
-          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename', activityId: '62e291bc10e0ab61bd691794' });
+          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename' });
 
 
         expect(xssSpy).toHaveBeenCalled();
         expect(xssSpy).toHaveBeenCalled();
         expect(pageEventSpy).toHaveBeenCalledWith('rename');
         expect(pageEventSpy).toHaveBeenCalledWith('rename');
@@ -482,7 +482,7 @@ describe('PageService', () => {
       test('rename page with isRecursively', async() => {
       test('rename page with isRecursively', async() => {
 
 
         const resultPage = await crowi.pageService.renamePage(parentForRename4, '/renamed4', testUser2, { isRecursively: true },
         const resultPage = await crowi.pageService.renamePage(parentForRename4, '/renamed4', testUser2, { isRecursively: true },
-          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename', activityId: '62e291bc10e0ab61bd691794' });
+          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename' });
 
 
         expect(xssSpy).toHaveBeenCalled();
         expect(xssSpy).toHaveBeenCalled();
         expect(renameDescendantsWithStreamSpy).toHaveBeenCalled();
         expect(renameDescendantsWithStreamSpy).toHaveBeenCalled();
@@ -496,7 +496,7 @@ describe('PageService', () => {
       test('rename page with different tree with isRecursively', async() => {
       test('rename page with different tree with isRecursively', async() => {
 
 
         const resultPage = await crowi.pageService.renamePage(parentForRename5, '/parentForRename5/renamedChild', testUser1, { isRecursively: true },
         const resultPage = await crowi.pageService.renamePage(parentForRename5, '/parentForRename5/renamedChild', testUser1, { isRecursively: true },
-          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename', activityId: '62e291bc10e0ab61bd691794' });
+          { ip: '::ffff:127.0.0.1', endpoint: '/_api/v3/pages/rename' });
         const wrongPage = await Page.findOne({ path: '/parentForRename5/renamedChild/renamedChild' });
         const wrongPage = await Page.findOne({ path: '/parentForRename5/renamedChild/renamedChild' });
         const expectPage = await Page.findOne({ path: '/parentForRename5/renamedChild' });
         const expectPage = await Page.findOne({ path: '/parentForRename5/renamedChild' });
 
 
@@ -651,7 +651,10 @@ describe('PageService', () => {
     });
     });
 
 
     test('delete page without options', async() => {
     test('delete page without options', async() => {
-      const resultPage = await crowi.pageService.deletePage(parentForDelete1, testUser2, { });
+      const resultPage = await crowi.pageService.deletePage(parentForDelete1, testUser2, { }, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/delete',
+      });
 
 
       expect(getDeletedPageNameSpy).toHaveBeenCalled();
       expect(getDeletedPageNameSpy).toHaveBeenCalled();
       expect(deleteDescendantsWithStreamSpy).not.toHaveBeenCalled();
       expect(deleteDescendantsWithStreamSpy).not.toHaveBeenCalled();
@@ -668,7 +671,10 @@ describe('PageService', () => {
     });
     });
 
 
     test('delete page with isRecursively', async() => {
     test('delete page with isRecursively', async() => {
-      const resultPage = await crowi.pageService.deletePage(parentForDelete2, testUser2, { }, true);
+      const resultPage = await crowi.pageService.deletePage(parentForDelete2, testUser2, { }, true, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/delete',
+      });
 
 
       expect(getDeletedPageNameSpy).toHaveBeenCalled();
       expect(getDeletedPageNameSpy).toHaveBeenCalled();
       expect(deleteDescendantsWithStreamSpy).toHaveBeenCalled();
       expect(deleteDescendantsWithStreamSpy).toHaveBeenCalled();
@@ -738,7 +744,10 @@ describe('PageService', () => {
     });
     });
 
 
     test('delete completely without options', async() => {
     test('delete completely without options', async() => {
-      await crowi.pageService.deleteCompletely(parentForDeleteCompletely, testUser2, { });
+      await crowi.pageService.deleteCompletely(parentForDeleteCompletely, testUser2, { }, false, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/deletecompletely',
+      });
 
 
       expect(deleteCompletelyOperationSpy).toHaveBeenCalled();
       expect(deleteCompletelyOperationSpy).toHaveBeenCalled();
       expect(deleteCompletelyDescendantsWithStreamSpy).not.toHaveBeenCalled();
       expect(deleteCompletelyDescendantsWithStreamSpy).not.toHaveBeenCalled();
@@ -748,7 +757,10 @@ describe('PageService', () => {
 
 
 
 
     test('delete completely with isRecursively', async() => {
     test('delete completely with isRecursively', async() => {
-      await crowi.pageService.deleteCompletely(parentForDeleteCompletely, testUser2, { }, true);
+      await crowi.pageService.deleteCompletely(parentForDeleteCompletely, testUser2, { }, true, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/deletecompletely',
+      });
 
 
       expect(deleteCompletelyOperationSpy).toHaveBeenCalled();
       expect(deleteCompletelyOperationSpy).toHaveBeenCalled();
       expect(deleteCompletelyDescendantsWithStreamSpy).toHaveBeenCalled();
       expect(deleteCompletelyDescendantsWithStreamSpy).toHaveBeenCalled();
@@ -771,7 +783,10 @@ describe('PageService', () => {
     });
     });
 
 
     test('revert deleted page when the redirect from page exists', async() => {
     test('revert deleted page when the redirect from page exists', async() => {
-      const resultPage = await crowi.pageService.revertDeletedPage(parentForRevert1, testUser2);
+      const resultPage = await crowi.pageService.revertDeletedPage(parentForRevert1, testUser2, {}, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/revert',
+      });
 
 
       expect(getRevertDeletedPageNameSpy).toHaveBeenCalledWith(parentForRevert1.path);
       expect(getRevertDeletedPageNameSpy).toHaveBeenCalledWith(parentForRevert1.path);
       expect(revertDeletedDescendantsWithStreamSpy).not.toHaveBeenCalled();
       expect(revertDeletedDescendantsWithStreamSpy).not.toHaveBeenCalled();
@@ -789,7 +804,10 @@ describe('PageService', () => {
         return null;
         return null;
       });
       });
 
 
-      const resultPage = await crowi.pageService.revertDeletedPage(parentForRevert2, testUser2, {}, true);
+      const resultPage = await crowi.pageService.revertDeletedPage(parentForRevert2, testUser2, {}, true, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/revert',
+      });
 
 
       expect(getRevertDeletedPageNameSpy).toHaveBeenCalledWith(parentForRevert2.path);
       expect(getRevertDeletedPageNameSpy).toHaveBeenCalledWith(parentForRevert2.path);
       expect(findByPathSpy).toHaveBeenCalledWith('/parentForRevert2');
       expect(findByPathSpy).toHaveBeenCalledWith('/parentForRevert2');

+ 46 - 16
packages/app/test/integration/service/v5.non-public-page.test.ts

@@ -1104,10 +1104,10 @@ describe('PageService page operations with non-public pages', () => {
   });
   });
   describe('Delete', () => {
   describe('Delete', () => {
 
 
-    const deletePage = async(page, user, options, isRecursively) => {
+    const deletePage = async(page, user, options, isRecursively, activityParameters?) => {
       const mockedDeleteRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteRecursivelyMainOperation').mockReturnValue(null);
       const mockedDeleteRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteRecursivelyMainOperation').mockReturnValue(null);
 
 
-      const deletedPage = await crowi.pageService.deletePage(page, user, options, isRecursively);
+      const deletedPage = await crowi.pageService.deletePage(page, user, options, isRecursively, activityParameters);
 
 
       const argsForDeleteRecursivelyMainOperation = mockedDeleteRecursivelyMainOperation.mock.calls[0];
       const argsForDeleteRecursivelyMainOperation = mockedDeleteRecursivelyMainOperation.mock.calls[0];
 
 
@@ -1126,7 +1126,10 @@ describe('PageService page operations with non-public pages', () => {
         expect(_pageT).toBeTruthy();
         expect(_pageT).toBeTruthy();
 
 
         const isRecursively = false;
         const isRecursively = false;
-        await deletePage(_pageT, dummyUser1, {}, isRecursively);
+        await deletePage(_pageT, dummyUser1, {}, isRecursively, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/rename',
+        });
 
 
         const pageT = await Page.findOne({ path: `/trash${_pathT}` });
         const pageT = await Page.findOne({ path: `/trash${_pathT}` });
         const pageN = await Page.findOne({ path: _pathT }); // should not exist
         const pageN = await Page.findOne({ path: _pathT }); // should not exist
@@ -1143,7 +1146,10 @@ describe('PageService page operations with non-public pages', () => {
         expect(_page1).toBeTruthy();
         expect(_page1).toBeTruthy();
 
 
         const isRecursively = false;
         const isRecursively = false;
-        await deletePage(_page1, npDummyUser1, {}, isRecursively);
+        await deletePage(_page1, npDummyUser1, {}, isRecursively, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/rename',
+        });
 
 
         const pageN = await Page.findOne({ path: _path, grantedGroup: groupIdA });
         const pageN = await Page.findOne({ path: _path, grantedGroup: groupIdA });
         const page1 = await Page.findOne({ path: `/trash${_path}`, grantedGroup: groupIdA });
         const page1 = await Page.findOne({ path: `/trash${_path}`, grantedGroup: groupIdA });
@@ -1169,7 +1175,10 @@ describe('PageService page operations with non-public pages', () => {
         expect(_pageR).toBeTruthy();
         expect(_pageR).toBeTruthy();
 
 
         const isRecursively = true;
         const isRecursively = true;
-        await deletePage(_pageT, npDummyUser1, {}, isRecursively);
+        await deletePage(_pageT, npDummyUser1, {}, isRecursively, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/rename',
+        });
 
 
         const pageTNotExist = await Page.findOne({ path: _pathT, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA }); // A should not exist
         const pageTNotExist = await Page.findOne({ path: _pathT, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA }); // A should not exist
         const page1NotExist = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB }); // B should not exist
         const page1NotExist = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB }); // B should not exist
@@ -1199,10 +1208,10 @@ describe('PageService page operations with non-public pages', () => {
 
 
   });
   });
   describe('Delete completely', () => {
   describe('Delete completely', () => {
-    const deleteCompletely = async(page, user, options = {}, isRecursively = false, preventEmitting = false) => {
+    const deleteCompletely = async(page, user, options = {}, isRecursively = false, preventEmitting = false, activityParameters?) => {
       const mockedDeleteCompletelyRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteCompletelyRecursivelyMainOperation').mockReturnValue(null);
       const mockedDeleteCompletelyRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteCompletelyRecursivelyMainOperation').mockReturnValue(null);
 
 
-      await crowi.pageService.deleteCompletely(page, user, options, isRecursively, preventEmitting);
+      await crowi.pageService.deleteCompletely(page, user, options, isRecursively, preventEmitting, activityParameters);
 
 
       const argsForDeleteCompletelyRecursivelyMainOperation = mockedDeleteCompletelyRecursivelyMainOperation.mock.calls[0];
       const argsForDeleteCompletelyRecursivelyMainOperation = mockedDeleteCompletelyRecursivelyMainOperation.mock.calls[0];
 
 
@@ -1221,7 +1230,10 @@ describe('PageService page operations with non-public pages', () => {
         const _page = await Page.findOne({ path: _path, grant: Page.GRANT_RESTRICTED });
         const _page = await Page.findOne({ path: _path, grant: Page.GRANT_RESTRICTED });
         expect(_page).toBeTruthy();
         expect(_page).toBeTruthy();
 
 
-        await deleteCompletely(_page, dummyUser1, {}, false);
+        await deleteCompletely(_page, dummyUser1, {}, false, false, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/rename',
+        });
 
 
         const page = await Page.findOne({ path: _path, grant: Page.GRANT_RESTRICTED });
         const page = await Page.findOne({ path: _path, grant: Page.GRANT_RESTRICTED });
         expect(page).toBeNull();
         expect(page).toBeNull();
@@ -1233,7 +1245,10 @@ describe('PageService page operations with non-public pages', () => {
         const _page = await Page.findOne({ path: _path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
         const _page = await Page.findOne({ path: _path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
         expect(_page).toBeTruthy();
         expect(_page).toBeTruthy();
 
 
-        await deleteCompletely(_page, npDummyUser1, {}, false);
+        await deleteCompletely(_page, npDummyUser1, {}, false, false, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/rename',
+        });
 
 
         const page = await Page.findOne({ path: _path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
         const page = await Page.findOne({ path: _path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
         expect(page).toBeNull();
         expect(page).toBeNull();
@@ -1253,7 +1268,10 @@ describe('PageService page operations with non-public pages', () => {
         expect(_page3).toBeTruthy();
         expect(_page3).toBeTruthy();
         expect(_page4).toBeTruthy();
         expect(_page4).toBeTruthy();
 
 
-        await deleteCompletely(_page1, npDummyUser1, {}, true);
+        await deleteCompletely(_page1, npDummyUser1, {}, true, false, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/rename',
+        });
 
 
         const page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
         const page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
         const page2 = await Page.findOne({ path: _path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB });
         const page2 = await Page.findOne({ path: _path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB });
@@ -1268,10 +1286,10 @@ describe('PageService page operations with non-public pages', () => {
     });
     });
   });
   });
   describe('revert', () => {
   describe('revert', () => {
-    const revertDeletedPage = async(page, user, options = {}, isRecursively = false) => {
+    const revertDeletedPage = async(page, user, options = {}, isRecursively = false, activityParameters?) => {
       // mock return value
       // mock return value
       const mockedRevertRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'revertRecursivelyMainOperation').mockReturnValue(null);
       const mockedRevertRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'revertRecursivelyMainOperation').mockReturnValue(null);
-      const revertedPage = await crowi.pageService.revertDeletedPage(page, user, options, isRecursively);
+      const revertedPage = await crowi.pageService.revertDeletedPage(page, user, options, isRecursively, activityParameters);
 
 
       const argsForRecursivelyMainOperation = mockedRevertRecursivelyMainOperation.mock.calls[0];
       const argsForRecursivelyMainOperation = mockedRevertRecursivelyMainOperation.mock.calls[0];
 
 
@@ -1294,7 +1312,10 @@ describe('PageService page operations with non-public pages', () => {
       expect(tag).toBeTruthy();
       expect(tag).toBeTruthy();
       expect(deletedPageTagRelation).toBeTruthy();
       expect(deletedPageTagRelation).toBeTruthy();
 
 
-      await revertDeletedPage(trashedPage, dummyUser1, {}, false);
+      await revertDeletedPage(trashedPage, dummyUser1, {}, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/rename',
+      });
 
 
       const revertedPage = await Page.findOne({ path: '/np_revert1' });
       const revertedPage = await Page.findOne({ path: '/np_revert1' });
       const deltedPageBeforeRevert = await Page.findOne({ path: '/trash/np_revert1' });
       const deltedPageBeforeRevert = await Page.findOne({ path: '/trash/np_revert1' });
@@ -1321,7 +1342,10 @@ describe('PageService page operations with non-public pages', () => {
       expect(tag).toBeTruthy();
       expect(tag).toBeTruthy();
       expect(deletedPageTagRelation).toBeTruthy();
       expect(deletedPageTagRelation).toBeTruthy();
 
 
-      await revertDeletedPage(trashedPage, user1, {}, false);
+      await revertDeletedPage(trashedPage, user1, {}, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/revert',
+      });
 
 
       const revertedPage = await Page.findOne({ path: '/np_revert2' });
       const revertedPage = await Page.findOne({ path: '/np_revert2' });
       const trashedPageBR = await Page.findOne({ path: beforeRevertPath });
       const trashedPageBR = await Page.findOne({ path: beforeRevertPath });
@@ -1349,7 +1373,10 @@ describe('PageService page operations with non-public pages', () => {
       expect(revision1).toBeTruthy();
       expect(revision1).toBeTruthy();
       expect(revision2).toBeTruthy();
       expect(revision2).toBeTruthy();
 
 
-      await revertDeletedPage(trashedPage1, npDummyUser2, {}, true);
+      await revertDeletedPage(trashedPage1, npDummyUser2, {}, true, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/revert',
+      });
 
 
       const revertedPage = await Page.findOne({ path: '/np_revert3' });
       const revertedPage = await Page.findOne({ path: '/np_revert3' });
       const middlePage = await Page.findOne({ path: '/np_revert3/middle' });
       const middlePage = await Page.findOne({ path: '/np_revert3/middle' });
@@ -1388,7 +1415,10 @@ describe('PageService page operations with non-public pages', () => {
       expect(user).toBeTruthy();
       expect(user).toBeTruthy();
       expect(nonExistantPage3).toBeNull();
       expect(nonExistantPage3).toBeNull();
 
 
-      await revertDeletedPage(trashedPage1, user, {}, true);
+      await revertDeletedPage(trashedPage1, user, {}, true, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/revert',
+      });
       const revertedPage1 = await Page.findOne({ path: '/np_revert5' });
       const revertedPage1 = await Page.findOne({ path: '/np_revert5' });
       const newlyCreatedPage = await Page.findOne({ path: '/np_revert5/middle' });
       const newlyCreatedPage = await Page.findOne({ path: '/np_revert5/middle' });
       const revertedPage2 = await Page.findOne({ path: '/np_revert5/middle/np_revert6' });
       const revertedPage2 = await Page.findOne({ path: '/np_revert5/middle/np_revert6' });

+ 66 - 33
packages/app/test/integration/service/v5.public-page.test.ts

@@ -144,7 +144,6 @@ describe('PageService page operations with only public pages', () => {
     const pageIdForRename30 = new mongoose.Types.ObjectId();
     const pageIdForRename30 = new mongoose.Types.ObjectId();
 
 
     pageOpId1 = new mongoose.Types.ObjectId();
     pageOpId1 = new mongoose.Types.ObjectId();
-    const activityId1 = new mongoose.Types.ObjectId();
     const pageOpRevisionId1 = new mongoose.Types.ObjectId();
     const pageOpRevisionId1 = new mongoose.Types.ObjectId();
 
 
     // Create Pages
     // Create Pages
@@ -433,7 +432,6 @@ describe('PageService page operations with only public pages', () => {
         activityParameters: {
         activityParameters: {
           ip: '::ffff:127.0.0.1',
           ip: '::ffff:127.0.0.1',
           endpoint: '/_api/v3/pages/rename',
           endpoint: '/_api/v3/pages/rename',
-          activityId: activityId1,
         },
         },
         unprocessableExpiryDate: null,
         unprocessableExpiryDate: null,
       },
       },
@@ -1194,7 +1192,6 @@ describe('PageService page operations with only public pages', () => {
         await crowi.pageService.renamePage(rootPage, '/new_root', dummyUser1, {}, {
         await crowi.pageService.renamePage(rootPage, '/new_root', dummyUser1, {}, {
           ip: '::ffff:127.0.0.1',
           ip: '::ffff:127.0.0.1',
           endpoint: '/_api/v3/pages/rename',
           endpoint: '/_api/v3/pages/rename',
-          activityId: '62e291bc10e0ab61bd691794',
         });
         });
       }
       }
       catch (err) {
       catch (err) {
@@ -1214,7 +1211,6 @@ describe('PageService page operations with only public pages', () => {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
       const childPageBeforeRename = await Page.findOne({ path: '/v5_ChildForRename1' });
       const childPageBeforeRename = await Page.findOne({ path: '/v5_ChildForRename1' });
 
 
@@ -1236,7 +1232,6 @@ describe('PageService page operations with only public pages', () => {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
       const childPageBeforeRename = await Page.findOne({ path: '/v5_ChildForRename2' });
       const childPageBeforeRename = await Page.findOne({ path: '/v5_ChildForRename2' });
 
 
@@ -1259,7 +1254,6 @@ describe('PageService page operations with only public pages', () => {
       const renamedPage = await renamePage(childPage, newPath, dummyUser2, { updateMetadata: true }, {
       const renamedPage = await renamePage(childPage, newPath, dummyUser2, { updateMetadata: true }, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
 
 
       expect(xssSpy).toHaveBeenCalled();
       expect(xssSpy).toHaveBeenCalled();
@@ -1280,7 +1274,6 @@ describe('PageService page operations with only public pages', () => {
       const renamedPage = await renamePage(childPage, newPath, dummyUser2, { createRedirectPage: true }, {
       const renamedPage = await renamePage(childPage, newPath, dummyUser2, { createRedirectPage: true }, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
       const pageRedirect = await PageRedirect.findOne({ fromPath: oldPath, toPath: renamedPage.path });
       const pageRedirect = await PageRedirect.findOne({ fromPath: oldPath, toPath: renamedPage.path });
 
 
@@ -1303,7 +1296,6 @@ describe('PageService page operations with only public pages', () => {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
       // find child of renamed page
       // find child of renamed page
       const renamedGrandchild = await Page.findOne({ parent: renamedPage._id });
       const renamedGrandchild = await Page.findOne({ parent: renamedPage._id });
@@ -1333,7 +1325,6 @@ describe('PageService page operations with only public pages', () => {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
       const renamedPage = await renamePage(childPage, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
       const grandchildAfterRename = await Page.findOne({ parent: renamedPage._id });
       const grandchildAfterRename = await Page.findOne({ parent: renamedPage._id });
       const grandchildBeforeRename = await Page.findOne({ path: '/v5_ChildForRename7/v5_GrandchildForRename7' });
       const grandchildBeforeRename = await Page.findOne({ path: '/v5_ChildForRename7/v5_GrandchildForRename7' });
@@ -1357,7 +1348,6 @@ describe('PageService page operations with only public pages', () => {
         await renamePage(page, newPath, dummyUser1, {}, {
         await renamePage(page, newPath, dummyUser1, {}, {
           ip: '::ffff:127.0.0.1',
           ip: '::ffff:127.0.0.1',
           endpoint: '/_api/v3/pages/rename',
           endpoint: '/_api/v3/pages/rename',
-          activityId: '62e291bc10e0ab61bd691794',
         });
         });
       }
       }
       catch (err) {
       catch (err) {
@@ -1380,7 +1370,6 @@ describe('PageService page operations with only public pages', () => {
       await renamePage(page1, newPath, dummyUser1, {}, {
       await renamePage(page1, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
 
 
       const renamedPage = await Page.findOne({ path: newParentalPath + initialPathForPage1 });
       const renamedPage = await Page.findOne({ path: newParentalPath + initialPathForPage1 });
@@ -1421,7 +1410,6 @@ describe('PageService page operations with only public pages', () => {
       await renamePage(page1, newPath, dummyUser1, {}, {
       await renamePage(page1, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
 
 
       const renamedPage = await Page.findOne({ path: newParentalPath + initialPathForPage1 });
       const renamedPage = await Page.findOne({ path: newParentalPath + initialPathForPage1 });
@@ -1466,7 +1454,6 @@ describe('PageService page operations with only public pages', () => {
       await renamePage(page1, newPath, dummyUser1, {}, {
       await renamePage(page1, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
 
 
       const renamedPage = await Page.findOne({ path: newParentalPath + initialPathForPage1 });
       const renamedPage = await Page.findOne({ path: newParentalPath + initialPathForPage1 });
@@ -1618,7 +1605,6 @@ describe('PageService page operations with only public pages', () => {
       await renamePage(_page1, newPath, dummyUser1, {}, {
       await renamePage(_page1, newPath, dummyUser1, {}, {
         ip: '::ffff:127.0.0.1',
         ip: '::ffff:127.0.0.1',
         endpoint: '/_api/v3/pages/rename',
         endpoint: '/_api/v3/pages/rename',
-        activityId: '62e291bc10e0ab61bd691794',
       });
       });
 
 
       const page0 = await Page.findById(_page0._id); // new parent
       const page0 = await Page.findById(_page0._id); // new parent
@@ -1826,10 +1812,10 @@ describe('PageService page operations with only public pages', () => {
     });
     });
   });
   });
   describe('Delete', () => {
   describe('Delete', () => {
-    const deletePage = async(page, user, options, isRecursively) => {
+    const deletePage = async(page, user, options, isRecursively, activityParameters?) => {
       const mockedDeleteRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteRecursivelyMainOperation').mockReturnValue(null);
       const mockedDeleteRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteRecursivelyMainOperation').mockReturnValue(null);
 
 
-      const deletedPage = await crowi.pageService.deletePage(page, user, options, isRecursively);
+      const deletedPage = await crowi.pageService.deletePage(page, user, options, isRecursively, activityParameters);
 
 
       const argsForDeleteRecursivelyMainOperation = mockedDeleteRecursivelyMainOperation.mock.calls[0];
       const argsForDeleteRecursivelyMainOperation = mockedDeleteRecursivelyMainOperation.mock.calls[0];
 
 
@@ -1845,7 +1831,12 @@ describe('PageService page operations with only public pages', () => {
     test('Should NOT delete root page', async() => {
     test('Should NOT delete root page', async() => {
       let isThrown;
       let isThrown;
       expect(rootPage).toBeTruthy();
       expect(rootPage).toBeTruthy();
-      try { await deletePage(rootPage, dummyUser1, {}, false) }
+      try {
+        await deletePage(rootPage, dummyUser1, {}, false, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/delete',
+        });
+      }
       catch (err) { isThrown = true }
       catch (err) { isThrown = true }
 
 
       const page = await Page.findOne({ path: '/' });
       const page = await Page.findOne({ path: '/' });
@@ -1859,7 +1850,12 @@ describe('PageService page operations with only public pages', () => {
       expect(trashedPage).toBeTruthy();
       expect(trashedPage).toBeTruthy();
 
 
       let isThrown;
       let isThrown;
-      try { await deletePage(trashedPage, dummyUser1, {}, false) }
+      try {
+        await deletePage(trashedPage, dummyUser1, {}, false, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/delete',
+        });
+      }
       catch (err) { isThrown = true }
       catch (err) { isThrown = true }
 
 
       const page = await Page.findOne({ path: '/trash/v5_PageForDelete1' });
       const page = await Page.findOne({ path: '/trash/v5_PageForDelete1' });
@@ -1872,7 +1868,12 @@ describe('PageService page operations with only public pages', () => {
       const dummyUser1Page = await Page.findOne({ path: '/user/v5DummyUser1' });
       const dummyUser1Page = await Page.findOne({ path: '/user/v5DummyUser1' });
       expect(dummyUser1Page).toBeTruthy();
       expect(dummyUser1Page).toBeTruthy();
       let isThrown;
       let isThrown;
-      try { await deletePage(dummyUser1Page, dummyUser1, {}, false) }
+      try {
+        await deletePage(dummyUser1Page, dummyUser1, {}, false, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/delete',
+        });
+      }
       catch (err) { isThrown = true }
       catch (err) { isThrown = true }
 
 
       const page = await Page.findOne({ path: '/user/v5DummyUser1' });
       const page = await Page.findOne({ path: '/user/v5DummyUser1' });
@@ -1884,7 +1885,10 @@ describe('PageService page operations with only public pages', () => {
     test('Should delete single page', async() => {
     test('Should delete single page', async() => {
       const pageToDelete = await Page.findOne({ path: '/v5_PageForDelete2' });
       const pageToDelete = await Page.findOne({ path: '/v5_PageForDelete2' });
       expect(pageToDelete).toBeTruthy();
       expect(pageToDelete).toBeTruthy();
-      const deletedPage = await deletePage(pageToDelete, dummyUser1, {}, false);
+      const deletedPage = await deletePage(pageToDelete, dummyUser1, {}, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/delete',
+      });
       const page = await Page.findOne({ path: '/v5_PageForDelete2' });
       const page = await Page.findOne({ path: '/v5_PageForDelete2' });
 
 
       expect(page).toBeNull();
       expect(page).toBeNull();
@@ -1900,7 +1904,10 @@ describe('PageService page operations with only public pages', () => {
       expect(parentPage).toBeTruthy();
       expect(parentPage).toBeTruthy();
       expect(childPage).toBeTruthy();
       expect(childPage).toBeTruthy();
       expect(grandchildPage).toBeTruthy();
       expect(grandchildPage).toBeTruthy();
-      const deletedParentPage = await deletePage(parentPage, dummyUser1, {}, true);
+      const deletedParentPage = await deletePage(parentPage, dummyUser1, {}, true, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/delete',
+      });
       const deletedChildPage = await Page.findOne({ path: '/trash/v5_PageForDelete3/v5_PageForDelete4' });
       const deletedChildPage = await Page.findOne({ path: '/trash/v5_PageForDelete3/v5_PageForDelete4' });
       const deletedGrandchildPage = await Page.findOne({ path: '/trash/v5_PageForDelete3/v5_PageForDelete4/v5_PageForDelete5' });
       const deletedGrandchildPage = await Page.findOne({ path: '/trash/v5_PageForDelete3/v5_PageForDelete4/v5_PageForDelete5' });
 
 
@@ -1927,7 +1934,10 @@ describe('PageService page operations with only public pages', () => {
       expect(tag2).toBeTruthy();
       expect(tag2).toBeTruthy();
       expect(pageRelation1).toBeTruthy();
       expect(pageRelation1).toBeTruthy();
       expect(pageRelation2).toBeTruthy();
       expect(pageRelation2).toBeTruthy();
-      const deletedPage = await deletePage(pageToDelete, dummyUser1, {}, false);
+      const deletedPage = await deletePage(pageToDelete, dummyUser1, {}, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/delete',
+      });
       const page = await Page.findOne({ path: '/v5_PageForDelete6' });
       const page = await Page.findOne({ path: '/v5_PageForDelete6' });
       const deletedTagRelation1 = await PageTagRelation.findOne({ _id: pageRelation1._id });
       const deletedTagRelation1 = await PageTagRelation.findOne({ _id: pageRelation1._id });
       const deletedTagRelation2 = await PageTagRelation.findOne({ _id: pageRelation2._id });
       const deletedTagRelation2 = await PageTagRelation.findOne({ _id: pageRelation2._id });
@@ -1939,10 +1949,10 @@ describe('PageService page operations with only public pages', () => {
     });
     });
   });
   });
   describe('Delete completely', () => {
   describe('Delete completely', () => {
-    const deleteCompletely = async(page, user, options = {}, isRecursively = false, preventEmitting = false) => {
+    const deleteCompletely = async(page, user, options = {}, isRecursively = false, preventEmitting = false, activityParameters?) => {
       const mockedDeleteCompletelyRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteCompletelyRecursivelyMainOperation').mockReturnValue(null);
       const mockedDeleteCompletelyRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteCompletelyRecursivelyMainOperation').mockReturnValue(null);
 
 
-      await crowi.pageService.deleteCompletely(page, user, options, isRecursively, preventEmitting);
+      await crowi.pageService.deleteCompletely(page, user, options, isRecursively, preventEmitting, activityParameters);
 
 
       const argsForDeleteCompletelyRecursivelyMainOperation = mockedDeleteCompletelyRecursivelyMainOperation.mock.calls[0];
       const argsForDeleteCompletelyRecursivelyMainOperation = mockedDeleteCompletelyRecursivelyMainOperation.mock.calls[0];
 
 
@@ -1958,7 +1968,12 @@ describe('PageService page operations with only public pages', () => {
     test('Should NOT completely delete root page', async() => {
     test('Should NOT completely delete root page', async() => {
       expect(rootPage).toBeTruthy();
       expect(rootPage).toBeTruthy();
       let isThrown;
       let isThrown;
-      try { await deleteCompletely(rootPage, dummyUser1, {}, false) }
+      try {
+        await deleteCompletely(rootPage, dummyUser1, {}, false, false, {
+          ip: '::ffff:127.0.0.1',
+          endpoint: '/_api/v3/pages/deletecompletely',
+        });
+      }
       catch (err) { isThrown = true }
       catch (err) { isThrown = true }
       const page = await Page.findOne({ path: '/' });
       const page = await Page.findOne({ path: '/' });
       expect(page).toBeTruthy();
       expect(page).toBeTruthy();
@@ -1968,7 +1983,10 @@ describe('PageService page operations with only public pages', () => {
       const page = await Page.findOne({ path: '/v5_PageForDeleteCompletely1' });
       const page = await Page.findOne({ path: '/v5_PageForDeleteCompletely1' });
       expect(page).toBeTruthy();
       expect(page).toBeTruthy();
 
 
-      await deleteCompletely(page, dummyUser1, {}, false);
+      await deleteCompletely(page, dummyUser1, {}, false, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/deletecompletely',
+      });
       const deletedPage = await Page.findOne({ _id: page._id, path: '/v5_PageForDeleteCompletely1' });
       const deletedPage = await Page.findOne({ _id: page._id, path: '/v5_PageForDeleteCompletely1' });
 
 
       expect(deletedPage).toBeNull();
       expect(deletedPage).toBeNull();
@@ -2001,7 +2019,10 @@ describe('PageService page operations with only public pages', () => {
       expect(shareLink1).toBeTruthy();
       expect(shareLink1).toBeTruthy();
       expect(shareLink2).toBeTruthy();
       expect(shareLink2).toBeTruthy();
 
 
-      await deleteCompletely(parentPage, dummyUser1, {}, true);
+      await deleteCompletely(parentPage, dummyUser1, {}, true, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/deletecompletely',
+      });
       const deletedPages = await Page.find({ _id: { $in: [parentPage._id, childPage._id, grandchildPage._id] } });
       const deletedPages = await Page.find({ _id: { $in: [parentPage._id, childPage._id, grandchildPage._id] } });
       const deletedRevisions = await Revision.find({ pageId: { $in: [parentPage._id, grandchildPage._id] } });
       const deletedRevisions = await Revision.find({ pageId: { $in: [parentPage._id, grandchildPage._id] } });
       const tags = await Tag.find({ _id: { $in: [tag1?._id, tag2?._id] } });
       const tags = await Tag.find({ _id: { $in: [tag1?._id, tag2?._id] } });
@@ -2033,7 +2054,10 @@ describe('PageService page operations with only public pages', () => {
       const revision = await Revision.findOne({ pageId: page._id });
       const revision = await Revision.findOne({ pageId: page._id });
       expect(page).toBeTruthy();
       expect(page).toBeTruthy();
       expect(revision).toBeTruthy();
       expect(revision).toBeTruthy();
-      await deleteCompletely(page, dummyUser1, {}, false);
+      await deleteCompletely(page, dummyUser1, {}, false, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/deletecompletely',
+      });
       const deltedPage = await Page.findOne({ _id: page._id });
       const deltedPage = await Page.findOne({ _id: page._id });
       const deltedRevision = await Revision.findOne({ _id: revision._id });
       const deltedRevision = await Revision.findOne({ _id: revision._id });
 
 
@@ -2048,7 +2072,10 @@ describe('PageService page operations with only public pages', () => {
       expect(childPage).toBeTruthy();
       expect(childPage).toBeTruthy();
       expect(grandchildPage).toBeTruthy();
       expect(grandchildPage).toBeTruthy();
 
 
-      await deleteCompletely(childPage, dummyUser1, {}, false);
+      await deleteCompletely(childPage, dummyUser1, {}, false, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/deletecompletely',
+      });
       const parentPageAfterDelete = await Page.findOne({ path: '/v5_PageForDeleteCompletely6' });
       const parentPageAfterDelete = await Page.findOne({ path: '/v5_PageForDeleteCompletely6' });
       const childPageAfterDelete = await Page.findOne({ path: '/v5_PageForDeleteCompletely6/v5_PageForDeleteCompletely7' });
       const childPageAfterDelete = await Page.findOne({ path: '/v5_PageForDeleteCompletely6/v5_PageForDeleteCompletely7' });
       const grandchildPageAfterDelete = await Page.findOne({ path: '/v5_PageForDeleteCompletely6/v5_PageForDeleteCompletely7/v5_PageForDeleteCompletely8' });
       const grandchildPageAfterDelete = await Page.findOne({ path: '/v5_PageForDeleteCompletely6/v5_PageForDeleteCompletely7/v5_PageForDeleteCompletely8' });
@@ -2066,10 +2093,10 @@ describe('PageService page operations with only public pages', () => {
     });
     });
   });
   });
   describe('revert', () => {
   describe('revert', () => {
-    const revertDeletedPage = async(page, user, options = {}, isRecursively = false) => {
+    const revertDeletedPage = async(page, user, options = {}, isRecursively = false, activityParameters?) => {
       // mock return value
       // mock return value
       const mockedRevertRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'revertRecursivelyMainOperation').mockReturnValue(null);
       const mockedRevertRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'revertRecursivelyMainOperation').mockReturnValue(null);
-      const revertedPage = await crowi.pageService.revertDeletedPage(page, user, options, isRecursively);
+      const revertedPage = await crowi.pageService.revertDeletedPage(page, user, options, isRecursively, activityParameters);
 
 
       const argsForRecursivelyMainOperation = mockedRevertRecursivelyMainOperation.mock.calls[0];
       const argsForRecursivelyMainOperation = mockedRevertRecursivelyMainOperation.mock.calls[0];
 
 
@@ -2093,7 +2120,10 @@ describe('PageService page operations with only public pages', () => {
       expect(tag).toBeTruthy();
       expect(tag).toBeTruthy();
       expect(deletedPageTagRelation).toBeTruthy();
       expect(deletedPageTagRelation).toBeTruthy();
 
 
-      const revertedPage = await revertDeletedPage(deletedPage, dummyUser1, {}, false);
+      const revertedPage = await revertDeletedPage(deletedPage, dummyUser1, {}, false, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/revert',
+      });
       const pageTagRelation = await PageTagRelation.findOne({ relatedPage: deletedPage._id, relatedTag: tag?._id });
       const pageTagRelation = await PageTagRelation.findOne({ relatedPage: deletedPage._id, relatedTag: tag?._id });
 
 
       expect(revertedPage.parent).toStrictEqual(rootPage._id);
       expect(revertedPage.parent).toStrictEqual(rootPage._id);
@@ -2113,7 +2143,10 @@ describe('PageService page operations with only public pages', () => {
       expect(revision1).toBeTruthy();
       expect(revision1).toBeTruthy();
       expect(revision2).toBeTruthy();
       expect(revision2).toBeTruthy();
 
 
-      const revertedPage1 = await revertDeletedPage(deletedPage1, dummyUser1, {}, true);
+      const revertedPage1 = await revertDeletedPage(deletedPage1, dummyUser1, {}, true, {
+        ip: '::ffff:127.0.0.1',
+        endpoint: '/_api/v3/pages/revert',
+      });
       const revertedPage2 = await Page.findOne({ _id: deletedPage2._id });
       const revertedPage2 = await Page.findOne({ _id: deletedPage2._id });
       const newlyCreatedPage = await Page.findOne({ path: '/v5_revert2/v5_revert3' });
       const newlyCreatedPage = await Page.findOne({ path: '/v5_revert2/v5_revert3' });