|
@@ -14,6 +14,7 @@ import {
|
|
|
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';
|
|
|
import { IPage } from '~/interfaces/page';
|
|
import { IPage } from '~/interfaces/page';
|
|
|
|
|
+import { ObjectIdLike } from '../interfaces/mongoose-utils';
|
|
|
|
|
|
|
|
const debug = require('debug')('growi:services:page');
|
|
const debug = require('debug')('growi:services:page');
|
|
|
|
|
|
|
@@ -860,7 +861,7 @@ class PageService {
|
|
|
// replace with an empty page
|
|
// replace with an empty page
|
|
|
const shouldReplace = !isRecursively && await Page.exists({ parent: page._id });
|
|
const shouldReplace = !isRecursively && await Page.exists({ parent: page._id });
|
|
|
if (shouldReplace) {
|
|
if (shouldReplace) {
|
|
|
- await Page.replaceTargetWithEmptyPage(page);
|
|
|
|
|
|
|
+ await Page.replaceTargetWithPage(page);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isRecursively) {
|
|
if (isRecursively) {
|
|
@@ -1090,7 +1091,7 @@ class PageService {
|
|
|
// replace with an empty page
|
|
// replace with an empty page
|
|
|
const shouldReplace = !isRecursively && !isTrashPage(page.path) && await Page.exists({ parent: page._id });
|
|
const shouldReplace = !isRecursively && !isTrashPage(page.path) && await Page.exists({ parent: page._id });
|
|
|
if (shouldReplace) {
|
|
if (shouldReplace) {
|
|
|
- await Page.replaceTargetWithEmptyPage(page);
|
|
|
|
|
|
|
+ await Page.replaceTargetWithPage(page);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
await this.deleteCompletelyOperation(ids, paths);
|
|
await this.deleteCompletelyOperation(ids, paths);
|
|
@@ -1450,9 +1451,57 @@ class PageService {
|
|
|
await inAppNotificationService.emitSocketIo(targetUsers);
|
|
await inAppNotificationService.emitSocketIo(targetUsers);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async v5MigrationByPageIds(pageIds) {
|
|
|
|
|
- const Page = mongoose.model('Page');
|
|
|
|
|
|
|
+ async normalizeParentByPageIds(pageIds: ObjectIdLike[]): Promise<void> {
|
|
|
|
|
+ for await (const pageId of pageIds) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await this.normalizeParentByPageId(pageId);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ // socket.emit('normalizeParentByPageIds', { error: err.message }); TODO: use socket to tell user
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private async normalizeParentByPageId(pageId: ObjectIdLike) {
|
|
|
|
|
+ const Page = mongoose.model('Page') as unknown as PageModel;
|
|
|
|
|
+ const target = await Page.findById(pageId);
|
|
|
|
|
+ if (target == null) {
|
|
|
|
|
+ throw Error('target does not exist');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const {
|
|
|
|
|
+ path, grant, grantedUsers: grantedUserIds, grantedGroup: grantedGroupId,
|
|
|
|
|
+ } = target;
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * UserGroup & Owner validation
|
|
|
|
|
+ */
|
|
|
|
|
+ if (target.grant !== Page.GRANT_RESTRICTED) {
|
|
|
|
|
+ let isGrantNormalized = false;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const shouldCheckDescendants = true;
|
|
|
|
|
+
|
|
|
|
|
+ isGrantNormalized = await this.crowi.pageGrantService.isGrantNormalized(path, grant, grantedUserIds, grantedGroupId, shouldCheckDescendants);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ logger.error(`Failed to validate grant of page at "${path}"`, err);
|
|
|
|
|
+ throw err;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!isGrantNormalized) {
|
|
|
|
|
+ throw Error('This page cannot be migrated since the selected grant or grantedGroup is not assignable to this page.');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ throw Error('Restricted pages can not be migrated');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // getParentAndFillAncestors
|
|
|
|
|
+ const parent = await Page.getParentAndFillAncestors(target.path);
|
|
|
|
|
+
|
|
|
|
|
+ return Page.updateOne({ _id: pageId }, { parent: parent._id });
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ async normalizeParentRecursivelyByPageIds(pageIds) {
|
|
|
if (pageIds == null || pageIds.length === 0) {
|
|
if (pageIds == null || pageIds.length === 0) {
|
|
|
logger.error('pageIds is null or 0 length.');
|
|
logger.error('pageIds is null or 0 length.');
|
|
|
return;
|
|
return;
|
|
@@ -1467,7 +1516,7 @@ class PageService {
|
|
|
}
|
|
}
|
|
|
catch (err) {
|
|
catch (err) {
|
|
|
logger.error('V5 initial miration failed.', err);
|
|
logger.error('V5 initial miration failed.', err);
|
|
|
- // socket.emit('v5InitialMirationFailed', { error: err.message }); TODO: use socket to tell user
|
|
|
|
|
|
|
+ // socket.emit('normalizeParentRecursivelyByPageIds', { error: err.message }); TODO: use socket to tell user
|
|
|
|
|
|
|
|
throw err;
|
|
throw err;
|
|
|
}
|
|
}
|