Przeglądaj źródła

Commonize validator

Shun Miyazawa 1 rok temu
rodzic
commit
3aa3317e5e

+ 4 - 84
apps/app/src/features/openai/server/routes/ai-assistant.ts

@@ -1,8 +1,6 @@
-import { type IUserHasId, GroupType } from '@growi/core';
+import { type IUserHasId } from '@growi/core';
 import { ErrorV3 } from '@growi/core/dist/models';
-import { isGrobPatternPath, isCreatablePage } from '@growi/core/dist/utils/page-path-utils';
 import type { Request, RequestHandler } from 'express';
-import { type ValidationChain, body } from 'express-validator';
 
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
@@ -10,14 +8,14 @@ import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
 import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';
 import loggerFactory from '~/utils/logger';
 
-import { type IApiv3AiAssistantCreateParams, AiAssistantShareScope, AiAssistantAccessScope } from '../../interfaces/ai-assistant';
+import { type IApiv3AiAssistantCreateParams } from '../../interfaces/ai-assistant';
 import { getOpenaiService } from '../services/openai';
 
 import { certifyAiService } from './middlewares/certify-ai-service';
+import { upsertAiAssistantValidator } from './middlewares/upsert-ai-assistant-validator';
 
 const logger = loggerFactory('growi:routes:apiv3:openai:create-ai-assistant');
 
-
 type CreateAssistantFactory = (crowi: Crowi) => RequestHandler[];
 
 type Req = Request<undefined, Response, IApiv3AiAssistantCreateParams> & {
@@ -27,86 +25,8 @@ type Req = Request<undefined, Response, IApiv3AiAssistantCreateParams> & {
 export const createAiAssistantFactory: CreateAssistantFactory = (crowi) => {
   const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi);
 
-  const validator: ValidationChain[] = [
-    body('name')
-      .isString()
-      .withMessage('name must be a string')
-      .not()
-      .isEmpty()
-      .withMessage('name is required')
-      .escape(),
-
-    body('description')
-      .optional()
-      .isString()
-      .withMessage('description must be a string')
-      .escape(),
-
-    body('additionalInstruction')
-      .optional()
-      .isString()
-      .withMessage('additionalInstruction must be a string')
-      .escape(),
-
-    body('pagePathPatterns')
-      .isArray()
-      .withMessage('pagePathPatterns must be an array of strings')
-      .not()
-      .isEmpty()
-      .withMessage('pagePathPatterns must not be empty'),
-
-    body('pagePathPatterns.*') // each item of pagePathPatterns
-      .isString()
-      .withMessage('pagePathPatterns must be an array of strings')
-      .notEmpty()
-      .withMessage('pagePathPatterns must not be empty')
-      .custom((value: string) => {
-
-        // check if the value is a grob pattern path
-        if (value.includes('*')) {
-          return isGrobPatternPath(value) && isCreatablePage(value.replace('*', ''));
-        }
-
-        return isCreatablePage(value);
-      }),
-
-    body('grantedGroupsForShareScope')
-      .optional()
-      .isArray()
-      .withMessage('grantedGroupsForShareScope must be an array'),
-
-    body('grantedGroupsForShareScope.*.type') // each item of grantedGroupsForShareScope
-      .isIn(Object.values(GroupType))
-      .withMessage('Invalid grantedGroupsForShareScope type value'),
-
-    body('grantedGroupsForShareScope.*.item') // each item of grantedGroupsForShareScope
-      .isMongoId()
-      .withMessage('Invalid grantedGroupsForShareScope item value'),
-
-    body('grantedGroupsForAccessScope')
-      .optional()
-      .isArray()
-      .withMessage('grantedGroupsForAccessScope must be an array'),
-
-    body('grantedGroupsForAccessScope.*.type') // each item of grantedGroupsForAccessScope
-      .isIn(Object.values(GroupType))
-      .withMessage('Invalid grantedGroupsForAccessScope type value'),
-
-    body('grantedGroupsForAccessScope.*.item') // each item of grantedGroupsForAccessScope
-      .isMongoId()
-      .withMessage('Invalid grantedGroupsForAccessScope item value'),
-
-    body('shareScope')
-      .isIn(Object.values(AiAssistantShareScope))
-      .withMessage('Invalid shareScope value'),
-
-    body('accessScope')
-      .isIn(Object.values(AiAssistantAccessScope))
-      .withMessage('Invalid accessScope value'),
-  ];
-
   return [
-    accessTokenParser, loginRequiredStrictly, certifyAiService, validator, apiV3FormValidator,
+    accessTokenParser, loginRequiredStrictly, certifyAiService, upsertAiAssistantValidator, apiV3FormValidator,
     async(req: Req, res: ApiV3Response) => {
       try {
         const aiAssistantData = { ...req.body, owner: req.user._id };

+ 83 - 0
apps/app/src/features/openai/server/routes/middlewares/upsert-ai-assistant-validator.ts

@@ -0,0 +1,83 @@
+import { GroupType } from '@growi/core';
+import { isGrobPatternPath, isCreatablePage } from '@growi/core/dist/utils/page-path-utils';
+import { type ValidationChain, body } from 'express-validator';
+
+import { AiAssistantShareScope, AiAssistantAccessScope } from '../../../interfaces/ai-assistant';
+
+export const upsertAiAssistantValidator: ValidationChain[] = [
+  body('name')
+    .isString()
+    .withMessage('name must be a string')
+    .not()
+    .isEmpty()
+    .withMessage('name is required')
+    .escape(),
+
+  body('description')
+    .optional()
+    .isString()
+    .withMessage('description must be a string')
+    .escape(),
+
+  body('additionalInstruction')
+    .optional()
+    .isString()
+    .withMessage('additionalInstruction must be a string')
+    .escape(),
+
+  body('pagePathPatterns')
+    .isArray()
+    .withMessage('pagePathPatterns must be an array of strings')
+    .not()
+    .isEmpty()
+    .withMessage('pagePathPatterns must not be empty'),
+
+  body('pagePathPatterns.*') // each item of pagePathPatterns
+    .isString()
+    .withMessage('pagePathPatterns must be an array of strings')
+    .notEmpty()
+    .withMessage('pagePathPatterns must not be empty')
+    .custom((value: string) => {
+
+      // check if the value is a grob pattern path
+      if (value.includes('*')) {
+        return isGrobPatternPath(value) && isCreatablePage(value.replace('*', ''));
+      }
+
+      return isCreatablePage(value);
+    }),
+
+  body('grantedGroupsForShareScope')
+    .optional()
+    .isArray()
+    .withMessage('grantedGroupsForShareScope must be an array'),
+
+  body('grantedGroupsForShareScope.*.type') // each item of grantedGroupsForShareScope
+    .isIn(Object.values(GroupType))
+    .withMessage('Invalid grantedGroupsForShareScope type value'),
+
+  body('grantedGroupsForShareScope.*.item') // each item of grantedGroupsForShareScope
+    .isMongoId()
+    .withMessage('Invalid grantedGroupsForShareScope item value'),
+
+  body('grantedGroupsForAccessScope')
+    .optional()
+    .isArray()
+    .withMessage('grantedGroupsForAccessScope must be an array'),
+
+  body('grantedGroupsForAccessScope.*.type') // each item of grantedGroupsForAccessScope
+    .isIn(Object.values(GroupType))
+    .withMessage('Invalid grantedGroupsForAccessScope type value'),
+
+  body('grantedGroupsForAccessScope.*.item') // each item of grantedGroupsForAccessScope
+    .isMongoId()
+    .withMessage('Invalid grantedGroupsForAccessScope item value'),
+
+  body('shareScope')
+    .isIn(Object.values(AiAssistantShareScope))
+    .withMessage('Invalid shareScope value'),
+
+  body('accessScope')
+    .isIn(Object.values(AiAssistantAccessScope))
+    .withMessage('Invalid accessScope value'),
+];

+ 5 - 82
apps/app/src/features/openai/server/routes/update-ai-assistant.ts

@@ -1,8 +1,7 @@
-import { type IUserHasId, GroupType } from '@growi/core';
+import { type IUserHasId } from '@growi/core';
 import { ErrorV3 } from '@growi/core/dist/models';
-import { isGrobPatternPath, isCreatablePage } from '@growi/core/dist/utils/page-path-utils';
 import type { Request, RequestHandler } from 'express';
-import { type ValidationChain, param, body } from 'express-validator';
+import { type ValidationChain, param } from 'express-validator';
 
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
@@ -10,14 +9,14 @@ import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
 import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';
 import loggerFactory from '~/utils/logger';
 
-import { type AiAssistantUpdateData, AiAssistantShareScope, AiAssistantAccessScope } from '../../interfaces/ai-assistant';
+import { type AiAssistantUpdateData } from '../../interfaces/ai-assistant';
 import { getOpenaiService } from '../services/openai';
 
 import { certifyAiService } from './middlewares/certify-ai-service';
+import { upsertAiAssistantValidator } from './middlewares/upsert-ai-assistant-validator';
 
 const logger = loggerFactory('growi:routes:apiv3:openai:update-ai-assistants');
 
-
 type UpdateAiAssistantsFactory = (crowi: Crowi) => RequestHandler[];
 
 type ReqParams = {
@@ -35,83 +34,7 @@ export const updateAiAssistantsFactory: UpdateAiAssistantsFactory = (crowi) => {
 
   const validator: ValidationChain[] = [
     param('id').isMongoId().withMessage('aiAssistant id is required'),
-    body('name')
-      .optional()
-      .isString()
-      .withMessage('name must be a string')
-      .escape(),
-
-    body('description')
-      .optional()
-      .isString()
-      .withMessage('description must be a string')
-      .escape(),
-
-    body('additionalInstruction')
-      .optional()
-      .isString()
-      .withMessage('additionalInstruction must be a string')
-      .escape(),
-
-    body('pagePathPatterns')
-      .optional()
-      .isArray()
-      .withMessage('pagePathPatterns must be an array of strings')
-      .not()
-      .isEmpty()
-      .withMessage('pagePathPatterns must not be empty'),
-
-    body('pagePathPatterns.*') // each item of pagePathPatterns
-      .isString()
-      .withMessage('pagePathPatterns must be an array of strings')
-      .not()
-      .isEmpty()
-      .withMessage('pagePathPatterns must not be empty')
-      .custom((value: string) => {
-
-        // check if the value is a grob pattern path
-        if (value.includes('*')) {
-          return isGrobPatternPath(value) && isCreatablePage(value.replace('*', ''));
-        }
-
-        return isCreatablePage(value);
-      }),
-
-    body('grantedGroupsForShareScope')
-      .optional()
-      .isArray()
-      .withMessage('grantedGroupsForShareScope must be an array'),
-
-    body('grantedGroupsForShareScope.*.type') // each item of grantedGroupsForShareScope
-      .isIn(Object.values(GroupType))
-      .withMessage('Invalid grantedGroupsForShareScope type value'),
-
-    body('grantedGroupsForShareScope.*.item') // each item of grantedGroupsForShareScope
-      .isMongoId()
-      .withMessage('Invalid grantedGroupsForShareScope item value'),
-
-    body('grantedGroupsForAccessScope')
-      .optional()
-      .isArray()
-      .withMessage('grantedGroupsForAccessScope must be an array'),
-
-    body('grantedGroupsForAccessScope.*.type') // each item of grantedGroupsForAccessScope
-      .isIn(Object.values(GroupType))
-      .withMessage('Invalid grantedGroupsForAccessScope type value'),
-
-    body('grantedGroupsForAccessScope.*.item') // each item of grantedGroupsForAccessScope
-      .isMongoId()
-      .withMessage('Invalid grantedGroupsForAccessScope item value'),
-
-    body('shareScope')
-      .optional()
-      .isIn(Object.values(AiAssistantShareScope))
-      .withMessage('Invalid shareScope value'),
-
-    body('accessScope')
-      .optional()
-      .isIn(Object.values(AiAssistantAccessScope))
-      .withMessage('Invalid accessScope value'),
+    ...upsertAiAssistantValidator,
   ];
 
   return [