Quellcode durchsuchen

Implementation of revision.origin field

Shun Miyazawa vor 2 Jahren
Ursprung
Commit
2a8e8950c9

+ 3 - 8
apps/app/src/interfaces/apiv3/page.ts

@@ -1,5 +1,5 @@
 import type {
 import type {
-  IPageHasId, IRevisionHasId, ITag,
+  IPageHasId, IRevisionHasId, ITag, Origin,
 } from '@growi/core';
 } from '@growi/core';
 
 
 import type { IOptionsForCreate, IOptionsForUpdate } from '../page';
 import type { IOptionsForCreate, IOptionsForUpdate } from '../page';
@@ -12,6 +12,8 @@ export type IApiv3PageCreateParams = IOptionsForCreate & {
   body?: string,
   body?: string,
   pageTags?: string[],
   pageTags?: string[],
 
 
+  origin?: Origin,
+
   isSlackEnabled?: boolean,
   isSlackEnabled?: boolean,
   slackChannels?: string,
   slackChannels?: string,
 };
 };
@@ -22,13 +24,6 @@ export type IApiv3PageCreateResponse = {
   revision: IRevisionHasId,
   revision: IRevisionHasId,
 };
 };
 
 
-export const Origin = {
-  View: 'view',
-  Editor: 'editor',
-} as const;
-
-export type Origin = typeof Origin[keyof typeof Origin];
-
 export type IApiv3PageUpdateParams = IOptionsForUpdate & {
 export type IApiv3PageUpdateParams = IOptionsForUpdate & {
   pageId: string,
   pageId: string,
   revisionId?: string,
   revisionId?: string,

+ 3 - 1
apps/app/src/interfaces/page.ts

@@ -1,5 +1,5 @@
 import type {
 import type {
-  GroupType, IGrantedGroup, IPageHasId, Nullable, PageGrant,
+  GroupType, IGrantedGroup, IPageHasId, Nullable, PageGrant, Origin,
 } from '@growi/core';
 } from '@growi/core';
 
 
 import type { IPageOperationProcessData } from './page-operation';
 import type { IPageOperationProcessData } from './page-operation';
@@ -33,6 +33,7 @@ export type IDeleteManyPageApiv3Result = {
 };
 };
 
 
 export type IOptionsForUpdate = {
 export type IOptionsForUpdate = {
+  origin?: Origin
   grant?: PageGrant,
   grant?: PageGrant,
   userRelatedGrantUserGroupIds?: IGrantedGroup[],
   userRelatedGrantUserGroupIds?: IGrantedGroup[],
   // isSyncRevisionToHackmd?: boolean,
   // isSyncRevisionToHackmd?: boolean,
@@ -44,5 +45,6 @@ export type IOptionsForCreate = {
   grantUserGroupIds?: IGrantedGroup[],
   grantUserGroupIds?: IGrantedGroup[],
   overwriteScopesOfDescendants?: boolean,
   overwriteScopesOfDescendants?: boolean,
 
 
+  origin?: Origin
   wip?: boolean,
   wip?: boolean,
 };
 };

+ 5 - 1
apps/app/src/server/models/revision.js

@@ -1,3 +1,5 @@
+import { allOrigin } from '@growi/core';
+
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 // disable no-return-await for model functions
 // disable no-return-await for model functions
@@ -29,6 +31,7 @@ module.exports = function(crowi) {
     format: { type: String, default: 'markdown' },
     format: { type: String, default: 'markdown' },
     author: { type: ObjectId, ref: 'User' },
     author: { type: ObjectId, ref: 'User' },
     hasDiffToPrev: { type: Boolean },
     hasDiffToPrev: { type: Boolean },
+    origin: { type: String, enum: allOrigin },
   }, {
   }, {
     timestamps: { createdAt: true, updatedAt: false },
     timestamps: { createdAt: true, updatedAt: false },
   });
   });
@@ -38,7 +41,7 @@ module.exports = function(crowi) {
     return this.updateMany({ pageId }, { $set: updateData });
     return this.updateMany({ pageId }, { $set: updateData });
   };
   };
 
 
-  revisionSchema.statics.prepareRevision = function(pageData, body, previousBody, user, options) {
+  revisionSchema.statics.prepareRevision = function(pageData, body, previousBody, user, origin, options) {
     const Revision = this;
     const Revision = this;
 
 
     if (!options) {
     if (!options) {
@@ -56,6 +59,7 @@ module.exports = function(crowi) {
     newRevision.body = body;
     newRevision.body = body;
     newRevision.format = format;
     newRevision.format = format;
     newRevision.author = user._id;
     newRevision.author = user._id;
+    newRevision.origin = origin;
     if (pageData.revision != null) {
     if (pageData.revision != null) {
       newRevision.hasDiffToPrev = body !== previousBody;
       newRevision.hasDiffToPrev = body !== previousBody;
     }
     }

+ 4 - 2
apps/app/src/server/routes/apiv3/page/create-page.ts

@@ -1,3 +1,4 @@
+import { allOrigin } from '@growi/core';
 import type {
 import type {
   IPage, IUser, IUserHasId,
   IPage, IUser, IUserHasId,
 } from '@growi/core';
 } from '@growi/core';
@@ -117,6 +118,7 @@ export const createPageHandlersFactory: CreatePageHandlersFactory = (crowi) => {
     body('isSlackEnabled').optional().isBoolean().withMessage('isSlackEnabled must be boolean'),
     body('isSlackEnabled').optional().isBoolean().withMessage('isSlackEnabled must be boolean'),
     body('slackChannels').optional().isString().withMessage('slackChannels must be string'),
     body('slackChannels').optional().isString().withMessage('slackChannels must be string'),
     body('wip').optional().isBoolean().withMessage('wip must be boolean'),
     body('wip').optional().isBoolean().withMessage('wip must be boolean'),
+    body('origin').optional().isIn(allOrigin).withMessage('origin must be "view" or "editor"'),
   ];
   ];
 
 
 
 
@@ -227,10 +229,10 @@ export const createPageHandlersFactory: CreatePageHandlersFactory = (crowi) => {
       let createdPage;
       let createdPage;
       try {
       try {
         const {
         const {
-          grant, grantUserGroupIds, overwriteScopesOfDescendants, wip,
+          grant, grantUserGroupIds, overwriteScopesOfDescendants, wip, origin,
         } = req.body;
         } = req.body;
 
 
-        const options: IOptionsForCreate = { overwriteScopesOfDescendants, wip };
+        const options: IOptionsForCreate = { overwriteScopesOfDescendants, wip, origin };
         if (grant != null) {
         if (grant != null) {
           options.grant = grant;
           options.grant = grant;
           options.grantUserGroupIds = grantUserGroupIds;
           options.grantUserGroupIds = grantUserGroupIds;

+ 5 - 11
apps/app/src/server/routes/apiv3/page/update-page.ts

@@ -1,14 +1,15 @@
+import { Origin } from '@growi/core';
 import type {
 import type {
   IPage, IRevisionHasId, IUserHasId,
   IPage, IRevisionHasId, IUserHasId,
 } from '@growi/core';
 } from '@growi/core';
 import { ErrorV3 } from '@growi/core/dist/models';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 import type { Request, RequestHandler } from 'express';
-import type { ValidationChain, CustomValidator } from 'express-validator';
+import type { ValidationChain } from 'express-validator';
 import { body } from 'express-validator';
 import { body } from 'express-validator';
 import mongoose from 'mongoose';
 import mongoose from 'mongoose';
 
 
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
-import { type IApiv3PageUpdateParams, Origin } from '~/interfaces/apiv3';
+import { type IApiv3PageUpdateParams } from '~/interfaces/apiv3';
 import type { IOptionsForUpdate } from '~/interfaces/page';
 import type { IOptionsForUpdate } from '~/interfaces/page';
 import { RehypeSanitizeOption } from '~/interfaces/rehype';
 import { RehypeSanitizeOption } from '~/interfaces/rehype';
 import type Crowi from '~/server/crowi';
 import type Crowi from '~/server/crowi';
@@ -59,13 +60,6 @@ export const updatePageHandlersFactory: UpdatePageHandlersFactory = (crowi) => {
     return new Xss(xssOption);
     return new Xss(xssOption);
   })();
   })();
 
 
-  const validateOrigin: CustomValidator = (value) => {
-    if (value === Origin.View || value === Origin.Editor) {
-      return true;
-    }
-    return false;
-  };
-
   // define validators for req.body
   // define validators for req.body
   const validator: ValidationChain[] = [
   const validator: ValidationChain[] = [
     body('pageId').exists().not().isEmpty({ ignore_whitespace: true })
     body('pageId').exists().not().isEmpty({ ignore_whitespace: true })
@@ -80,7 +74,7 @@ export const updatePageHandlersFactory: UpdatePageHandlersFactory = (crowi) => {
     body('overwriteScopesOfDescendants').optional().isBoolean().withMessage('overwriteScopesOfDescendants must be boolean'),
     body('overwriteScopesOfDescendants').optional().isBoolean().withMessage('overwriteScopesOfDescendants must be boolean'),
     body('isSlackEnabled').optional().isBoolean().withMessage('isSlackEnabled must be boolean'),
     body('isSlackEnabled').optional().isBoolean().withMessage('isSlackEnabled must be boolean'),
     body('slackChannels').optional().isString().withMessage('slackChannels must be string'),
     body('slackChannels').optional().isString().withMessage('slackChannels must be string'),
-    body('origin').optional().custom(validateOrigin).withMessage('origin must be "view" or "editor"'),
+    body('origin').optional().isIn(Object.values(Origin)).withMessage('origin must be "view" or "editor"'),
   ];
   ];
 
 
 
 
@@ -158,7 +152,7 @@ export const updatePageHandlersFactory: UpdatePageHandlersFactory = (crowi) => {
       let updatedPage;
       let updatedPage;
       try {
       try {
         const { grant, userRelatedGrantUserGroupIds, overwriteScopesOfDescendants } = req.body;
         const { grant, userRelatedGrantUserGroupIds, overwriteScopesOfDescendants } = req.body;
-        const options: IOptionsForUpdate = { overwriteScopesOfDescendants };
+        const options: IOptionsForUpdate = { overwriteScopesOfDescendants, origin };
         if (grant != null) {
         if (grant != null) {
           options.grant = grant;
           options.grant = grant;
           options.userRelatedGrantUserGroupIds = userRelatedGrantUserGroupIds;
           options.userRelatedGrantUserGroupIds = userRelatedGrantUserGroupIds;

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

@@ -3825,7 +3825,7 @@ class PageService implements IPageService {
 
 
     // Create revision
     // Create revision
     const Revision = mongoose.model('Revision') as any; // TODO: Typescriptize model
     const Revision = mongoose.model('Revision') as any; // TODO: Typescriptize model
-    const newRevision = Revision.prepareRevision(savedPage, body, null, user);
+    const newRevision = Revision.prepareRevision(savedPage, body, null, user, options.origin);
     savedPage = await pushRevision(savedPage, newRevision, user);
     savedPage = await pushRevision(savedPage, newRevision, user);
     await savedPage.populateDataToShowRevision();
     await savedPage.populateDataToShowRevision();
 
 
@@ -4214,15 +4214,15 @@ class PageService implements IPageService {
     let savedPage = await newPageData.save();
     let savedPage = await newPageData.save();
 
 
     // Update body
     // Update body
-    const isBodyPresent = body != null && previousBody != null;
+    const isBodyPresent = body != null;
     const shouldUpdateBody = isBodyPresent;
     const shouldUpdateBody = isBodyPresent;
     if (shouldUpdateBody) {
     if (shouldUpdateBody) {
-      const newRevision = await Revision.prepareRevision(newPageData, body, previousBody, user);
+      const origin = options.origin;
+      const newRevision = await Revision.prepareRevision(newPageData, body, previousBody, user, origin);
       savedPage = await pushRevision(savedPage, newRevision, user);
       savedPage = await pushRevision(savedPage, newRevision, user);
       await savedPage.populateDataToShowRevision();
       await savedPage.populateDataToShowRevision();
     }
     }
 
 
-
     this.pageEvent.emit('update', savedPage, user);
     this.pageEvent.emit('update', savedPage, user);
 
 
     // Update ex children's parent
     // Update ex children's parent

+ 10 - 0
packages/core/src/interfaces/revision.ts

@@ -1,12 +1,22 @@
 import type { HasObjectId } from './has-object-id';
 import type { HasObjectId } from './has-object-id';
 import type { IUser } from './user';
 import type { IUser } from './user';
 
 
+export const Origin = {
+  View: 'view',
+  Editor: 'editor',
+} as const;
+
+export type Origin = typeof Origin[keyof typeof Origin];
+
+export const allOrigin = Object.values(Origin);
+
 export type IRevision = {
 export type IRevision = {
   body: string,
   body: string,
   author: IUser,
   author: IUser,
   hasDiffToPrev: boolean;
   hasDiffToPrev: boolean;
   createdAt: Date,
   createdAt: Date,
   updatedAt: Date,
   updatedAt: Date,
+  origin?: Origin,
 }
 }
 
 
 export type IRevisionHasId = IRevision & HasObjectId;
 export type IRevisionHasId = IRevision & HasObjectId;