ryoji-s 2 лет назад
Родитель
Сommit
663f1c4c59
2 измененных файлов с 41 добавлено и 27 удалено
  1. 4 23
      apps/app/src/server/routes/apiv3/pages.js
  2. 37 4
      apps/app/src/server/service/page.ts

+ 4 - 23
apps/app/src/server/routes/apiv3/pages.js

@@ -925,34 +925,15 @@ module.exports = (crowi) => {
       return res.apiv3Err(new ErrorV3('The grant of the retrieved page is not restricted'), 500);
     }
 
-    // Since the decision to delete or not a user's homepage is an asynchronous process,
-    // filtering is done here on the user homepages and other pages for performance optimization.
-    let { filteredPages, userHomepages } = pagesToDelete.reduce((result, page) => {
-      if (isUsersHomepage(page.path)) {
-        result.userHomepages.push(page);
-      }
-      else {
-        result.filteredPages.push(page);
-      }
-      return result;
-    },
-    { filteredPages: [], userHomepages: [] });
-
-    const pagesCanBeDeleted = [];
-    const canDeleteCompletely = page => page.isEmpty || crowi.pageService.canDeleteCompletely(page.path, page.creator, req.user, isRecursively);
-    const canDelete = page => page.isEmpty || crowi.pageService.canDelete(page.path, page.creator, req.user, isRecursively);
-
+    let pagesCanBeDeleted = [];
     if (isCompletely) {
-      pagesCanBeDeleted.push(...crowi.pageService.filterPagesByCanDeleteCompletely(filteredPages, req.user, isRecursively));
+      pagesCanBeDeleted = await crowi.pageService.filterPagesByCanDeleteCompletely(pagesToDelete, req.user, isRecursively);
     }
     else {
-      filteredPages = filteredPages.filter(page => page.isEmpty || page.isUpdatable(pageIdToRevisionIdMap[page._id].toString()));
-      userHomepages = userHomepages.filter(page => page.isEmpty || page.isUpdatable(pageIdToRevisionIdMap[page._id].toString()));
-      pagesCanBeDeleted.push(...crowi.pageService.filterPagesByCanDelete(filteredPages, req.user, isRecursively));
+      const filteredPages = pagesToDelete.filter(page => page.isEmpty || page.isUpdatable(pageIdToRevisionIdMap[page._id].toString()));
+      pagesCanBeDeleted = await crowi.pageService.filterPagesByCanDelete(filteredPages, req.user, isRecursively);
     }
 
-    await addDeletableUserHomepages(isCompletely ? canDeleteCompletely : canDelete, userHomepages, pagesCanBeDeleted);
-
     if (pagesCanBeDeleted.length === 0) {
       const msg = 'No pages can be deleted.';
       return res.apiv3Err(new ErrorV3(msg), 500);

+ 37 - 4
apps/app/src/server/service/page.ts

@@ -231,12 +231,45 @@ class PageService {
     return false;
   }
 
-  filterPagesByCanDeleteCompletely(pages, user, isRecursively: boolean) {
-    return pages.filter(p => p.isEmpty || this.canDeleteCompletely(p.path, p.creator, user, isRecursively));
+  private async addDeletableUserHomepages(userHomepages: PageDocument[]): Promise<PageDocument[]> {
+    if (!this.canDeleteUserHomepageByConfig()) {
+      return [];
+    }
+
+    const User = mongoose.model('User');
+    const usernames = userHomepages.map(page => getUsernameByPath(page.path)) as string[];
+    const existingUsernames = await User.distinct<string>('username', { username: { $in: usernames } });
+
+    const isUserHomepageDeletable = (page: PageDocument) => {
+      const username = getUsernameByPath(page.path);
+      return !existingUsernames.includes(username);
+    };
+
+    return userHomepages.filter(isUserHomepageDeletable);
+  }
+
+  private async filterPages(
+      pages: PageDocument[],
+      user: IUserHasId,
+      isRecursively: boolean,
+      canDeleteFunction: (path: string, creatorId: ObjectIdLike, operator: any, isRecursively: boolean) => boolean,
+  ): Promise<PageDocument[]> {
+    const filteredPages = pages.filter(p => p.isEmpty || canDeleteFunction(p.path, p.creator, user, isRecursively));
+
+    const userHomepages = filteredPages.filter(p => isUsersHomepage(p.path));
+    const deletableUserHomepages = await this.addDeletableUserHomepages(userHomepages);
+
+    return filteredPages
+      .filter(p => !isUsersHomepage(p.path))
+      .concat(deletableUserHomepages);
+  }
+
+  async filterPagesByCanDeleteCompletely(pages: PageDocument[], user: IUserHasId, isRecursively: boolean): Promise<PageDocument[]> {
+    return this.filterPages(pages, user, isRecursively, this.canDeleteCompletely);
   }
 
-  filterPagesByCanDelete(pages, user, isRecursively: boolean) {
-    return pages.filter(p => p.isEmpty || this.canDelete(p.path, p.creator, user, isRecursively));
+  async filterPagesByCanDelete(pages: PageDocument[], user: IUserHasId, isRecursively: boolean): Promise<PageDocument[]> {
+    return this.filterPages(pages, user, isRecursively, this.canDelete);
   }
 
   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types