Kaynağa Gözat

impl isAiAssistantUsable

Shun Miyazawa 1 yıl önce
ebeveyn
işleme
6332d98f04

+ 5 - 2
apps/app/src/features/openai/server/routes/thread.ts

@@ -46,10 +46,13 @@ export const createThreadHandlersFactory: CreateThreadFactory = (crowi) => {
       try {
       try {
         const { aiAssistantId, threadId } = req.body;
         const { aiAssistantId, threadId } = req.body;
 
 
-        // リクエストした user が AiAssistant の owner or shareScope に含まれているかチェックする
-        const vectorStoreRelation = await openaiService.getVectorStoreRelation(aiAssistantId);
+        const isAiAssistantUsable = await openaiService.isAiAssistantUsable(aiAssistantId, req.user);
+        if (!isAiAssistantUsable) {
+          return res.apiv3Err(new ErrorV3('The specified AI assistant is not usable'), 400);
+        }
 
 
         const filteredThreadId = threadId != null ? filterXSS(threadId) : undefined;
         const filteredThreadId = threadId != null ? filterXSS(threadId) : undefined;
+        const vectorStoreRelation = await openaiService.getVectorStoreRelation(aiAssistantId);
 
 
         const thread = await openaiService.getOrCreateThread(req.user._id, vectorStoreRelation, filteredThreadId);
         const thread = await openaiService.getOrCreateThread(req.user._id, vectorStoreRelation, filteredThreadId);
         return res.apiv3({ thread });
         return res.apiv3({ thread });

+ 37 - 0
apps/app/src/features/openai/server/services/openai.ts

@@ -71,6 +71,7 @@ export interface IOpenaiService {
   deleteObsoleteVectorStoreFile(limit: number, apiCallInterval: number): Promise<void>; // for CronJob
   deleteObsoleteVectorStoreFile(limit: number, apiCallInterval: number): Promise<void>; // for CronJob
   // rebuildVectorStoreAll(): Promise<void>;
   // rebuildVectorStoreAll(): Promise<void>;
   // rebuildVectorStore(page: HydratedDocument<PageDocument>): Promise<void>;
   // rebuildVectorStore(page: HydratedDocument<PageDocument>): Promise<void>;
+  isAiAssistantUsable(aiAssistantId: string, user: IUserHasId): Promise<boolean>;
   createAiAssistant(data: Omit<AiAssistant, 'vectorStore'>): Promise<AiAssistantDocument>;
   createAiAssistant(data: Omit<AiAssistant, 'vectorStore'>): Promise<AiAssistantDocument>;
   updateAiAssistant(aiAssistantId: string, data: Omit<AiAssistant, 'vectorStore'>): Promise<AiAssistantDocument>;
   updateAiAssistant(aiAssistantId: string, data: Omit<AiAssistant, 'vectorStore'>): Promise<AiAssistantDocument>;
   getAccessibleAiAssistants(user: IUserHasId): Promise<AccessibleAiAssistants>
   getAccessibleAiAssistants(user: IUserHasId): Promise<AccessibleAiAssistants>
@@ -556,6 +557,42 @@ class OpenaiService implements IOpenaiService {
     }
     }
   }
   }
 
 
+  async isAiAssistantUsable(aiAssistantId: string, user: IUserHasId): Promise<boolean> {
+    const aiAssistant = await AiAssistantModel.findById(aiAssistantId);
+
+    if (aiAssistant == null) {
+      throw createError(404, 'AiAssistant document does not exist');
+    }
+
+    const isOwner = getIdStringForRef(aiAssistant.owner) === getIdStringForRef(user._id);
+
+    if (aiAssistant.shareScope === AiAssistantShareScope.PUBLIC_ONLY) {
+      return true;
+    }
+
+    if ((aiAssistant.shareScope === AiAssistantShareScope.OWNER) && isOwner) {
+      return true;
+    }
+
+    if ((aiAssistant.shareScope === AiAssistantShareScope.SAME_AS_ACCESS_SCOPE) && (aiAssistant.accessScope === AiAssistantAccessScope.OWNER) && isOwner) {
+      return true;
+    }
+
+    if ((aiAssistant.shareScope === AiAssistantShareScope.GROUPS)
+      || ((aiAssistant.shareScope === AiAssistantShareScope.SAME_AS_ACCESS_SCOPE) && (aiAssistant.accessScope === AiAssistantAccessScope.GROUPS))) {
+      const userGroupIds = [
+        ...(await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user)),
+        ...(await ExternalUserGroupRelation.findAllUserGroupIdsRelatedToUser(user)),
+      ].map(group => group.toString());
+
+      const grantedGroupIdsForShareScope = aiAssistant.grantedGroupsForShareScope?.map(group => getIdStringForRef(group.item)) ?? [];
+      const isShared = userGroupIds.some(userGroupId => grantedGroupIdsForShareScope.includes(userGroupId));
+      return isShared;
+    }
+
+    return false;
+  }
+
   async createAiAssistant(data: Omit<AiAssistant, 'vectorStore'>): Promise<AiAssistantDocument> {
   async createAiAssistant(data: Omit<AiAssistant, 'vectorStore'>): Promise<AiAssistantDocument> {
     await this.validateGrantedUserGroupsForAiAssistant(
     await this.validateGrantedUserGroupsForAiAssistant(
       data.owner,
       data.owner,