|
|
@@ -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 };
|