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

Merge branch 'dev/6.2.x' into feat/130903-delete-user-homepage-if-user-not-found

ryoji-s 2 лет назад
Родитель
Сommit
c192f057f3

+ 7 - 2
apps/app/src/server/events/user.ts

@@ -1,8 +1,10 @@
 import EventEmitter from 'events';
 
-import type { IUserHasId } from '@growi/core';
+import type { IPage, IUserHasId } from '@growi/core';
 import { pagePathUtils } from '@growi/core/dist/utils';
+import mongoose from 'mongoose';
 
+import type { PageModel } from '~/server/models/page';
 import loggerFactory from '~/utils/logger';
 
 const logger = loggerFactory('growi:events:user');
@@ -23,11 +25,14 @@ class UserEvent extends EventEmitter {
       return;
     }
 
-    const Page = this.crowi.model('Page');
+    const Page = mongoose.model<IPage, PageModel>('Page');
     const userHomepagePath = pagePathUtils.userHomepagePath(user);
 
     let page = await Page.findByPath(userHomepagePath, true);
 
+    // TODO: Make it more type safe
+    // Since the type of page.creator is 'any', we resort to the following comparison,
+    // checking if page.creator.toString() is not equal to user._id.toString(). Our code covers null, string, or object types.
     if (page != null && page.creator != null && page.creator.toString() !== user._id.toString()) {
       await this.crowi.pageService.deleteCompletelyUserHomeBySystem(userHomepagePath);
       page = null;

+ 2 - 2
apps/app/src/server/middlewares/certify-shared-page-attachment/retrieve-valid-share-link.ts

@@ -15,9 +15,9 @@ export const retrieveValidShareLinkByReferer = async(referer: ValidReferer): Pro
     return null;
   }
 
-  const shareLinkId = referer;
+  const { shareLinkId } = referer;
   const shareLink = await ShareLink.findOne({
-    id: shareLinkId,
+    _id: shareLinkId,
   });
   if (shareLink == null || shareLink.isExpired()) {
     logger.info(`ShareLink ('${shareLinkId}') is not found or has already expired.`);

+ 1 - 0
apps/app/src/server/models/page.ts

@@ -65,6 +65,7 @@ export interface PageModel extends Model<PageDocument> {
   generateGrantCondition(
     user, userGroups, includeAnyoneWithTheLink?: boolean, showPagesRestrictedByOwner?: boolean, showPagesRestrictedByGroup?: boolean,
   ): { $or: any[] }
+  removeLeafEmptyPagesRecursively(pageId: ObjectIdLike): Promise<void>
 
   PageQueryBuilder: typeof PageQueryBuilder
 

+ 22 - 8
apps/app/src/server/service/page.ts

@@ -5,11 +5,11 @@ import type {
   Ref, HasObjectId, IUserHasId, IUser,
   IPage, IPageInfo, IPageInfoAll, IPageInfoForEntity, IPageWithMeta,
 } from '@growi/core';
-import { PageGrant, PageStatus } from '@growi/core';
+import { PageGrant, PageStatus, getIdForRef } from '@growi/core';
 import {
   pagePathUtils, pathUtils,
 } from '@growi/core/dist/utils';
-import { collectAncestorPaths } from '@growi/core/dist/utils/page-path-utils';
+import { collectAncestorPaths, isUsersHomepage } from '@growi/core/dist/utils/page-path-utils';
 import escapeStringRegexp from 'escape-string-regexp';
 import mongoose, { ObjectId, Cursor } from 'mongoose';
 import streamToPromise from 'stream-to-promise';
@@ -2049,24 +2049,38 @@ class PageService {
    * @throws {Error} - If an error occurs during the deletion process.
    */
   async deleteCompletelyUserHomeBySystem(userHomepagePath: string): Promise<void> {
-    const Page = this.crowi.model('Page');
+    if (!isUsersHomepage(userHomepagePath)) {
+      const msg = 'input value is not user homepage path.';
+      logger.error(msg);
+      throw new Error(msg);
+    }
+
+    const Page = mongoose.model<IPage, PageModel>('Page');
     const userHomepage = await Page.findByPath(userHomepagePath, true);
 
     if (userHomepage == null) {
-      logger.error('user homepage is not found.');
-      return;
+      const msg = 'user homepage is not found.';
+      logger.error(msg);
+      throw new Error(msg);
+    }
+
+    if (userHomepage.parent == null) {
+      const msg = 'user homepage parent is not found.';
+      logger.error(msg);
+      throw new Error(msg);
     }
 
     const shouldUseV4Process = this.shouldUseV4Process(userHomepage);
 
     const ids = [userHomepage._id];
     const paths = [userHomepage.path];
+    const parentId = getIdForRef(userHomepage.parent);
 
     try {
       if (!shouldUseV4Process) {
         // Ensure consistency of ancestors
         const inc = userHomepage.isEmpty ? -userHomepage.descendantCount : -(userHomepage.descendantCount + 1);
-        await this.updateDescendantCountOfAncestors(userHomepage.parent, inc, true);
+        await this.updateDescendantCountOfAncestors(parentId, inc, true);
       }
 
       // Delete the user's homepage
@@ -2074,7 +2088,7 @@ class PageService {
 
       if (!shouldUseV4Process) {
         // Remove leaf empty pages
-        await Page.removeLeafEmptyPagesRecursively(userHomepage.parent);
+        await Page.removeLeafEmptyPagesRecursively(parentId);
       }
 
       if (!userHomepage.isEmpty) {
@@ -2087,7 +2101,7 @@ class PageService {
       // Find descendant pages with system deletion condition
       const builder = new PageQueryBuilder(Page.find(), true)
         .addConditionForSystemDeletion()
-        .addConditionToListOnlyDescendants(userHomepage.path);
+        .addConditionToListOnlyDescendants(userHomepage.path, {});
 
       // Stream processing to delete descendant pages
       // ────────┤ start │─────────