Browse Source

putback the changes

Shunm634-source 3 years ago
parent
commit
56085bfdea

+ 47 - 1
packages/app/src/server/service/page.ts

@@ -25,6 +25,7 @@ import { createBatchStream } from '~/server/util/batch-stream';
 import loggerFactory from '~/utils/logger';
 import { prepareDeleteConfigValuesForCalc } from '~/utils/page-delete-config';
 
+import PageEvent from '../events/page';
 import { ObjectIdLike } from '../interfaces/mongoose-utils';
 import { PathAlreadyExistsError } from '../models/errors';
 import PageOperation, { PageActionStage, PageActionType, PageOperationDocument } from '../models/page-operation';
@@ -137,14 +138,18 @@ class PageService {
 
   constructor(crowi) {
     this.crowi = crowi;
+    this.pageEvent = crowi.event('page');
     this.tagEvent = crowi.event('tag');
 
+    // init
     this.initPageEvent();
   }
 
   private initPageEvent() {
+    // create
     this.pageEvent.on('create', this.pageEvent.onCreate);
 
+    // createMany
     this.pageEvent.on('createMany', this.pageEvent.onCreateMany);
     this.pageEvent.on('addSeenUsers', this.pageEvent.onAddSeenUsers);
   }
@@ -463,6 +468,7 @@ class PageService {
       update.updatedAt = new Date();
     }
     const renamedPage = await Page.findByIdAndUpdate(page._id, { $set: update }, { new: true });
+    this.pageEvent.emit('rename', page, user);
 
     // 5.increase parent's descendantCount.
     // see: https://dev.growi.org/62149d019311629d4ecd91cf#Handling%20of%20descendantCount%20in%20case%20of%20unexpected%20process%20interruption
@@ -654,6 +660,8 @@ class PageService {
       await PageRedirect.create({ fromPath: page.path, toPath: newPagePath });
     }
 
+    this.pageEvent.emit('rename');
+
     return renamedPage;
   }
 
@@ -727,6 +735,8 @@ class PageService {
         throw Error(`Failed to create PageRedirect documents: ${err}`);
       }
     }
+
+    this.pageEvent.emit('updateMany', pages, user);
   }
 
   private async renameDescendantsV4(pages, user, options, oldPagePathPrefix, newPagePathPrefix) {
@@ -778,6 +788,7 @@ class PageService {
         throw Error(`Failed to create PageRedirect documents: ${err}`);
       }
     }
+
     this.pageEvent.emit('updateMany', pages, user);
   }
 
@@ -794,6 +805,7 @@ class PageService {
     const pathRegExp = new RegExp(`^${escapeStringRegexp(targetPage.path)}`, 'i');
 
     const renameDescendants = this.renameDescendants.bind(this);
+    const pageEvent = this.pageEvent;
     let count = 0;
     const writeStream = new Writable({
       objectMode: true,
@@ -816,6 +828,8 @@ class PageService {
 
         // update path
         targetPage.path = newPagePath;
+        pageEvent.emit('syncDescendantsUpdate', targetPage, user);
+
         callback();
       },
     });
@@ -835,6 +849,7 @@ class PageService {
     const pathRegExp = new RegExp(`^${escapeStringRegexp(targetPage.path)}`, 'i');
 
     const renameDescendants = this.renameDescendants.bind(this);
+    const pageEvent = this.pageEvent;
     let count = 0;
     const writeStream = new Writable({
       objectMode: true,
@@ -854,6 +869,7 @@ class PageService {
         logger.debug(`Renaming pages has completed: (totalCount=${count})`);
         // update  path
         targetPage.path = newPagePath;
+        pageEvent.emit('syncDescendantsUpdate', targetPage, user);
         callback();
       },
     });
@@ -950,6 +966,7 @@ class PageService {
         newPagePath, page.revision.body, user, options,
       );
     }
+    this.pageEvent.emit('duplicate', page, user);
 
     // 4. Take over tags
     const originTags = await page.findRelatedTagsById();
@@ -1043,6 +1060,7 @@ class PageService {
     const createdPage = await this.crowi.pageService.create(
       newPagePath, page.revision.body, user, options,
     );
+    this.pageEvent.emit('duplicate', page, user);
 
     if (isRecursively) {
       this.duplicateDescendantsWithStream(page, newPagePath, user);
@@ -1210,6 +1228,7 @@ class PageService {
     const pathRegExp = new RegExp(`^${escapeStringRegexp(page.path)}`, 'i');
 
     const duplicateDescendants = this.duplicateDescendants.bind(this);
+    const pageEvent = this.pageEvent;
     let count = 0;
     let nNonEmptyDuplicatedPages = 0;
     const writeStream = new Writable({
@@ -1231,6 +1250,7 @@ class PageService {
         logger.debug(`Adding pages has completed: (totalCount=${count})`);
         // update  path
         page.path = newPagePath;
+        pageEvent.emit('syncDescendantsUpdate', page, user);
         callback();
       },
     });
@@ -1251,6 +1271,7 @@ class PageService {
     const pathRegExp = new RegExp(`^${escapeStringRegexp(page.path)}`, 'i');
 
     const duplicateDescendants = this.duplicateDescendants.bind(this);
+    const pageEvent = this.pageEvent;
     let count = 0;
     const writeStream = new Writable({
       objectMode: true,
@@ -1270,6 +1291,7 @@ class PageService {
         logger.debug(`Adding pages has completed: (totalCount=${count})`);
         // update  path
         page.path = newPagePath;
+        pageEvent.emit('syncDescendantsUpdate', page, user);
         callback();
       },
     });
@@ -1367,6 +1389,10 @@ class PageService {
        */
       this.deleteRecursivelyMainOperation(page, user, pageOp._id);
     }
+    else {
+
+      this.pageEvent.emit('delete', page, user);
+    }
 
     return deletedPage;
   }
@@ -1392,7 +1418,8 @@ class PageService {
         throw err;
       }
     }
-    this.pageEvent.emit('create', page, user);
+    this.pageEvent.emit('create', deletedPage, user);
+
     return deletedPage;
   }
 
@@ -1442,6 +1469,8 @@ class PageService {
         throw err;
       }
     }
+
+    this.pageEvent.emit('delete', page, user);
     this.pageEvent.emit('create', deletedPage, user);
 
     return deletedPage;
@@ -1500,6 +1529,9 @@ class PageService {
         throw new Error(`Failed to delete pages: ${err}`);
       }
     }
+    finally {
+      this.pageEvent.emit('syncDescendantsDelete', pages, user);
+    }
 
     try {
       await PageRedirect.bulkWrite(insertPageRedirectOperations);
@@ -1596,6 +1628,8 @@ class PageService {
 
     await this.deleteCompletelyOperation(ids, paths);
 
+    this.pageEvent.emit('syncDescendantsDelete', pages, user); // update as renamed page
+
     return;
   }
 
@@ -1670,6 +1704,9 @@ class PageService {
        */
       this.deleteCompletelyRecursivelyMainOperation(page, user, options, pageOp._id);
     }
+    else if (!page.isEmpty && !preventEmitting) {
+      this.pageEvent.emit('deleteCompletely', page, user);
+    }
 
     return;
   }
@@ -1694,6 +1731,10 @@ class PageService {
       this.deleteCompletelyDescendantsWithStream(page, user, options);
     }
 
+    if (!page.isEmpty && !preventEmitting) {
+      this.pageEvent.emit('deleteCompletely', page, user);
+    }
+
     return;
   }
 
@@ -1849,6 +1890,7 @@ class PageService {
 
     if (!isRecursively) {
       await this.updateDescendantCountOfAncestors(parent._id, 1, true);
+      this.pageEvent.emit('revert', page, user);
     }
     else {
       let pageOp;
@@ -1946,6 +1988,8 @@ class PageService {
     }, { new: true });
     await PageTagRelation.updateMany({ relatedPage: page._id }, { $set: { isPageTrashed: false } });
 
+    this.pageEvent.emit('revert', page, user);
+
     return updatedPage;
   }
 
@@ -3291,6 +3335,7 @@ class PageService {
     // Update descendantCount
     await this.updateDescendantCountOfAncestors(savedPage._id, 1, false);
 
+    // Emit create event
     this.pageEvent.emit('create', savedPage, user);
 
     // Delete PageRedirect if exists
@@ -3392,6 +3437,7 @@ class PageService {
     // Update descendantCount
     await this.updateDescendantCountOfAncestors(savedPage._id, 1, false);
 
+    // Emit create event
     this.pageEvent.emit('create', savedPage, dummyUser);
 
     return savedPage;

+ 23 - 0
packages/app/test/integration/service/page.test.js

@@ -423,12 +423,14 @@ describe('PageService', () => {
   });
 
   describe('rename page', () => {
+    let pageEventSpy;
     let renameDescendantsWithStreamSpy;
     // mock new Date() and Date.now()
     advanceTo(new Date(2000, 1, 1, 0, 0, 0));
     const dateToUse = new Date();
 
     beforeEach(async() => {
+      pageEventSpy = jest.spyOn(crowi.pageService.pageEvent, 'emit').mockImplementation();
       renameDescendantsWithStreamSpy = jest.spyOn(crowi.pageService, 'renameDescendantsWithStream').mockImplementation();
     });
 
@@ -440,6 +442,8 @@ describe('PageService', () => {
 
         expect(xssSpy).toHaveBeenCalled();
 
+        expect(pageEventSpy).toHaveBeenCalledWith('rename');
+
         expect(resultPage.path).toBe('/renamed1');
         expect(resultPage.updatedAt).toEqual(parentForRename1.updatedAt);
         expect(resultPage.lastUpdateUser).toEqual(testUser1._id);
@@ -451,6 +455,8 @@ describe('PageService', () => {
 
         expect(xssSpy).toHaveBeenCalled();
 
+        expect(pageEventSpy).toHaveBeenCalledWith('rename');
+
         expect(resultPage.path).toBe('/renamed2');
         expect(resultPage.updatedAt).toEqual(dateToUse);
         expect(resultPage.lastUpdateUser).toEqual(testUser2._id);
@@ -461,6 +467,7 @@ describe('PageService', () => {
         const resultPage = await crowi.pageService.renamePage(parentForRename3, '/renamed3', testUser2, { createRedirectPage: true });
 
         expect(xssSpy).toHaveBeenCalled();
+        expect(pageEventSpy).toHaveBeenCalledWith('rename');
 
         expect(resultPage.path).toBe('/renamed3');
         expect(resultPage.updatedAt).toEqual(parentForRename3.updatedAt);
@@ -473,6 +480,7 @@ describe('PageService', () => {
 
         expect(xssSpy).toHaveBeenCalled();
         expect(renameDescendantsWithStreamSpy).toHaveBeenCalled();
+        expect(pageEventSpy).toHaveBeenCalledWith('rename');
 
         expect(resultPage.path).toBe('/renamed4');
         expect(resultPage.updatedAt).toEqual(parentForRename4.updatedAt);
@@ -499,6 +507,7 @@ describe('PageService', () => {
       const resultPage = await Page.findOne({ path: '/renamed1/child' });
 
       expect(resultPage).not.toBeNull();
+      expect(pageEventSpy).toHaveBeenCalledWith('updateMany', [childForRename1], testUser2);
 
       expect(resultPage.path).toBe('/renamed1/child');
       expect(resultPage.updatedAt).toEqual(childForRename1.updatedAt);
@@ -513,6 +522,7 @@ describe('PageService', () => {
       const resultPage = await Page.findOne({ path: '/renamed2/child' });
 
       expect(resultPage).not.toBeNull();
+      expect(pageEventSpy).toHaveBeenCalledWith('updateMany', [childForRename2], testUser2);
 
       expect(resultPage.path).toBe('/renamed2/child');
       expect(resultPage.updatedAt).toEqual(dateToUse);
@@ -527,6 +537,7 @@ describe('PageService', () => {
       const resultPage = await Page.findOne({ path: '/renamed3/child' });
 
       expect(resultPage).not.toBeNull();
+      expect(pageEventSpy).toHaveBeenCalledWith('updateMany', [childForRename3], testUser2);
 
       expect(resultPage.path).toBe('/renamed3/child');
       expect(resultPage.updatedAt).toEqual(childForRename3.updatedAt);
@@ -621,12 +632,14 @@ describe('PageService', () => {
 
   describe('delete page', () => {
     let getDeletedPageNameSpy;
+    let pageEventSpy;
     let deleteDescendantsWithStreamSpy;
     const dateToUse = new Date('2000-01-01');
 
     beforeEach(async() => {
       jest.spyOn(global.Date, 'now').mockImplementation(() => dateToUse);
       getDeletedPageNameSpy = jest.spyOn(Page, 'getDeletedPageName');
+      pageEventSpy = jest.spyOn(crowi.pageService.pageEvent, 'emit');
       deleteDescendantsWithStreamSpy = jest.spyOn(crowi.pageService, 'deleteDescendantsWithStream').mockImplementation();
     });
 
@@ -643,6 +656,8 @@ describe('PageService', () => {
       expect(resultPage.updatedAt).toEqual(parentForDelete1.updatedAt);
       expect(resultPage.lastUpdateUser).toEqual(testUser1._id);
 
+      expect(pageEventSpy).toHaveBeenCalledWith('delete', parentForDelete1, testUser2);
+      expect(pageEventSpy).toHaveBeenCalledWith('create', resultPage, testUser2);
     });
 
     test('delete page with isRecursively', async() => {
@@ -658,6 +673,8 @@ describe('PageService', () => {
       expect(resultPage.updatedAt).toEqual(parentForDelete2.updatedAt);
       expect(resultPage.lastUpdateUser).toEqual(testUser1._id);
 
+      expect(pageEventSpy).toHaveBeenCalledWith('delete', parentForDelete2, testUser2);
+      expect(pageEventSpy).toHaveBeenCalledWith('create', resultPage, testUser2);
     });
 
 
@@ -675,6 +692,7 @@ describe('PageService', () => {
   });
 
   describe('delete page completely', () => {
+    let pageEventSpy;
     let deleteCompletelyOperationSpy;
     let deleteCompletelyDescendantsWithStreamSpy;
 
@@ -687,6 +705,7 @@ describe('PageService', () => {
     let removeAllAttachmentsSpy;
 
     beforeEach(async() => {
+      pageEventSpy = jest.spyOn(crowi.pageService.pageEvent, 'emit');
       deleteCompletelyOperationSpy = jest.spyOn(crowi.pageService, 'deleteCompletelyOperation');
       deleteCompletelyDescendantsWithStreamSpy = jest.spyOn(crowi.pageService, 'deleteCompletelyDescendantsWithStream').mockImplementation();
 
@@ -716,6 +735,8 @@ describe('PageService', () => {
 
       expect(deleteCompletelyOperationSpy).toHaveBeenCalled();
       expect(deleteCompletelyDescendantsWithStreamSpy).not.toHaveBeenCalled();
+
+      expect(pageEventSpy).toHaveBeenCalledWith('deleteCompletely', parentForDeleteCompletely, testUser2);
     });
 
 
@@ -724,6 +745,8 @@ describe('PageService', () => {
 
       expect(deleteCompletelyOperationSpy).toHaveBeenCalled();
       expect(deleteCompletelyDescendantsWithStreamSpy).toHaveBeenCalled();
+
+      expect(pageEventSpy).toHaveBeenCalledWith('deleteCompletely', parentForDeleteCompletely, testUser2);
     });
   });