Przeglądaj źródła

Resolved conflict

Taichi Masuyama 4 lat temu
rodzic
commit
8244d160b4
1 zmienionych plików z 36 dodań i 22 usunięć
  1. 36 22
      packages/app/src/server/service/page.ts

+ 36 - 22
packages/app/src/server/service/page.ts

@@ -9,7 +9,7 @@ import { serializePageSecurely } from '../models/serializers/page-serializer';
 import { createBatchStream } from '~/server/util/batch-stream';
 import { createBatchStream } from '~/server/util/batch-stream';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 import {
 import {
-  CreateMethod, generateGrantCondition, PageCreateOptions, PageDocument, PageModel,
+  CreateMethod, generateGrantCondition, PageCreateOptions, PageModel,
 } from '~/server/models/page';
 } from '~/server/models/page';
 import { stringifySnapshot } from '~/models/serializers/in-app-notification-snapshot/page';
 import { stringifySnapshot } from '~/models/serializers/in-app-notification-snapshot/page';
 import ActivityDefine from '../util/activityDefine';
 import ActivityDefine from '../util/activityDefine';
@@ -26,7 +26,7 @@ const debug = require('debug')('growi:services:page');
 
 
 const logger = loggerFactory('growi:services:page');
 const logger = loggerFactory('growi:services:page');
 const {
 const {
-  isCreatablePage, isTrashPage, isTopPage, isDeletablePage, omitDuplicateAreaPageFromPages,
+  isCreatablePage, isTrashPage, isTopPage, isDeletablePage, collectAncestorPaths, omitDuplicateAreaPageFromPages,
 } = pagePathUtils;
 } = pagePathUtils;
 
 
 const BULK_REINDEX_SIZE = 100;
 const BULK_REINDEX_SIZE = 100;
@@ -1990,21 +1990,18 @@ class PageService {
     }
     }
 
 
     /*
     /*
-     * Sub Operation (s)
+     * Main Operation (s)
      */
      */
     for await (const page of normalizablePages) {
     for await (const page of normalizablePages) {
-      await this.normalizeParentRecursivelySubOperation(page, user);
+      await this.normalizeParentRecursivelyMainOperation(page, user);
     }
     }
   }
   }
 
 
-  private async normalizeParentRecursivelySubOperation(page, user) {
-    const Page = mongoose.model('Page') as unknown as PageModel;
-
+  async normalizeParentRecursivelyMainOperation(page, user): Promise<void> {
     // TODO: insertOne PageOperationBlock
     // TODO: insertOne PageOperationBlock
 
 
-    const regexps = [new RegExp(`^${escapeStringRegexp(page.path)}`, 'i')];
     try {
     try {
-      await this.normalizeParentRecursively(null, regexps);
+      await this.normalizeParentRecursively([page.path]);
     }
     }
     catch (err) {
     catch (err) {
       logger.error('V5 initial miration failed.', err);
       logger.error('V5 initial miration failed.', err);
@@ -2013,6 +2010,12 @@ class PageService {
       throw err;
       throw err;
     }
     }
 
 
+    await this.normalizeParentRecursivelySubOperation(page, user);
+  }
+
+  async normalizeParentRecursivelySubOperation(page, user): Promise<void> {
+    const Page = mongoose.model('Page') as unknown as PageModel;
+
     try {
     try {
       // update descendantCount of self and descendant pages first
       // update descendantCount of self and descendant pages first
       await this.updateDescendantCountOfSelfAndDescendants(page.path);
       await this.updateDescendantCountOfSelfAndDescendants(page.path);
@@ -2089,8 +2092,7 @@ class PageService {
 
 
     // then migrate
     // then migrate
     try {
     try {
-      const Page = mongoose.model('Page') as unknown as PageModel;
-      await this.normalizeParentRecursively(Page.GRANT_PUBLIC, null, true);
+      await this.normalizeParentRecursively(['/'], true);
     }
     }
     catch (err) {
     catch (err) {
       logger.error('V5 initial miration failed.', err);
       logger.error('V5 initial miration failed.', err);
@@ -2126,16 +2128,21 @@ class PageService {
   }
   }
 
 
   private async normalizeParentAndDescendantCountOfDescendants(path: string): Promise<void> {
   private async normalizeParentAndDescendantCountOfDescendants(path: string): Promise<void> {
-    const escapedPath = escapeStringRegexp(path);
-    const regexps = [new RegExp(`^${escapedPath}`, 'i')];
-    await this.normalizeParentRecursively(null, regexps);
+    await this.normalizeParentRecursively([path]);
 
 
     // update descendantCount of descendant pages
     // update descendantCount of descendant pages
     await this.updateDescendantCountOfSelfAndDescendants(path);
     await this.updateDescendantCountOfSelfAndDescendants(path);
   }
   }
 
 
+  async normalizeParentRecursively(paths: string[], publicOnly = false): Promise<void> {
+    const ancestorPaths = paths.flatMap(p => collectAncestorPaths(p));
+    const regexps = paths.map(p => new RegExp(`^${escapeStringRegexp(p)}`, 'i'));
+
+    return this._normalizeParentRecursively(regexps, ancestorPaths, publicOnly);
+  }
+
   // TODO: use websocket to show progress
   // TODO: use websocket to show progress
-  private async normalizeParentRecursively(grant, regexps, publicOnly = false): Promise<void> {
+  private async _normalizeParentRecursively(regexps: RegExp[], pathsToInclude: string[], publicOnly: boolean): Promise<void> {
     const BATCH_SIZE = 100;
     const BATCH_SIZE = 100;
     const PAGES_LIMIT = 1000;
     const PAGES_LIMIT = 1000;
     const Page = mongoose.model('Page') as unknown as PageModel;
     const Page = mongoose.model('Page') as unknown as PageModel;
@@ -2149,8 +2156,8 @@ class PageService {
       ],
       ],
     };
     };
 
 
-    if (grant != null) { // add grant condition if not null
-      grantFilter.$and = [...grantFilter.$and, { grant }];
+    if (publicOnly) { // add grant condition if not null
+      grantFilter.$and = [...grantFilter.$and, { grant: Page.GRANT_PUBLIC }];
     }
     }
 
 
     // generate filter
     // generate filter
@@ -2163,11 +2170,18 @@ class PageService {
         },
         },
       ],
       ],
     };
     };
-    if (regexps != null && regexps.length !== 0) {
+    let pathCondition: (RegExp | string)[] = [];
+    if (regexps.length > 0) {
+      pathCondition = [...regexps];
+    }
+    if (pathsToInclude.length > 0) {
+      pathCondition = [...pathCondition, ...pathsToInclude];
+    }
+    if (pathCondition.length > 0) {
       filter.$and.push({
       filter.$and.push({
         parent: null,
         parent: null,
         status: Page.STATUS_PUBLISHED,
         status: Page.STATUS_PUBLISHED,
-        path: { $in: regexps },
+        path: { $in: pathCondition },
       });
       });
     }
     }
 
 
@@ -2230,8 +2244,8 @@ class PageService {
             // ex. /parent/any_child OR /any_level1
             // ex. /parent/any_child OR /any_level1
             path: { $regex: new RegExp(`^${parentPath}(\\/[^/]+)\\/?$`, 'i') },
             path: { $regex: new RegExp(`^${parentPath}(\\/[^/]+)\\/?$`, 'i') },
           };
           };
-          if (grant != null) {
-            filter.grant = grant;
+          if (publicOnly) {
+            filter.grant = Page.GRANT_PUBLIC;
           }
           }
 
 
           return {
           return {
@@ -2280,7 +2294,7 @@ class PageService {
 
 
     const existsFilter = { $and: [...grantFilter.$and, ...filter.$and] };
     const existsFilter = { $and: [...grantFilter.$and, ...filter.$and] };
     if (await Page.exists(existsFilter) && shouldContinue) {
     if (await Page.exists(existsFilter) && shouldContinue) {
-      return this.normalizeParentRecursively(grant, regexps, publicOnly);
+      return this._normalizeParentRecursively(regexps, pathsToInclude, publicOnly);
     }
     }
 
 
   }
   }