[Security Assistant] Fix Attack discovery create conversation (#182622)

Resolves the bug with creating conversation
This commit is contained in:
Yuliia Naumenko 2024-05-03 20:42:00 -07:00 committed by GitHub
parent 0980742a04
commit 2123bbb9e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 73 additions and 9 deletions

View file

@ -6,9 +6,12 @@
*/
import { act, renderHook } from '@testing-library/react-hooks';
import { DefinedUseQueryResult } from '@tanstack/react-query';
import { useAssistantOverlay } from '.';
import { waitFor } from '@testing-library/react';
import { useFetchCurrentUserConversations } from '../api';
import { Conversation } from '../../assistant_context/types';
const mockUseAssistantContext = {
registerPromptContext: jest.fn(),
@ -23,6 +26,7 @@ jest.mock('../../assistant_context', () => {
useAssistantContext: () => mockUseAssistantContext,
};
});
jest.mock('../api/conversations/use_fetch_current_user_conversations');
jest.mock('../use_conversation', () => {
return {
useConversation: jest.fn(() => ({
@ -42,9 +46,43 @@ jest.mock('../../connectorland/use_load_connectors', () => {
};
});
const mockData = {
welcome_id: {
id: 'welcome_id',
title: 'Welcome',
category: 'assistant',
messages: [],
apiConfig: { connectorId: '123' },
replacements: {},
},
electric_sheep_id: {
id: 'electric_sheep_id',
category: 'assistant',
title: 'electric sheep',
messages: [],
apiConfig: { connectorId: '123' },
replacements: {},
},
};
describe('useAssistantOverlay', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.mocked(useFetchCurrentUserConversations).mockReturnValue({
data: mockData,
isLoading: false,
refetch: jest.fn().mockResolvedValue({
isLoading: false,
data: {
...mockData,
welcome_id: {
...mockData.welcome_id,
apiConfig: { newProp: true },
},
},
}),
isFetched: true,
} as unknown as DefinedUseQueryResult<Record<string, Conversation>, unknown>);
});
it('calls registerPromptContext with the expected context', async () => {

View file

@ -12,9 +12,11 @@ import { useAssistantContext } from '../../assistant_context';
import { getUniquePromptContextId } from '../../assistant_context/helpers';
import type { PromptContext } from '../prompt_context/types';
import { useConversation } from '../use_conversation';
import { getDefaultConnector } from '../helpers';
import { getDefaultConnector, mergeBaseWithPersistedConversations } from '../helpers';
import { getGenAiConfig } from '../../connectorland/helpers';
import { useLoadConnectors } from '../../connectorland/use_load_connectors';
import { FetchConversationsResponse, useFetchCurrentUserConversations } from '../api';
import { Conversation } from '../../assistant_context/types';
interface UseAssistantOverlay {
showAssistantOverlay: (show: boolean, silent?: boolean) => void;
@ -84,7 +86,18 @@ export const useAssistantOverlay = (
const defaultConnector = useMemo(() => getDefaultConnector(connectors), [connectors]);
const apiConfig = useMemo(() => getGenAiConfig(defaultConnector), [defaultConnector]);
const { getConversation, createConversation } = useConversation();
const { createConversation } = useConversation();
const onFetchedConversations = useCallback(
(conversationsData: FetchConversationsResponse): Record<string, Conversation> =>
mergeBaseWithPersistedConversations({}, conversationsData),
[]
);
const { data: conversations, isLoading } = useFetchCurrentUserConversations({
http,
onFetch: onFetchedConversations,
isAssistantEnabled: true,
});
// memoize the props so that we can use them in the effect below:
const _category: PromptContext['category'] = useMemo(() => category, [category]);
@ -116,13 +129,13 @@ export const useAssistantOverlay = (
const showAssistantOverlay = useCallback(
async (showOverlay: boolean, silent?: boolean) => {
let conversation;
try {
conversation = await getConversation(promptContextId, silent);
} catch (e) {
/* empty */
if (!isLoading) {
conversation = conversationTitle
? Object.values(conversations).find((conv) => conv.title === conversationTitle)
: undefined;
}
if (!conversation && defaultConnector) {
if (!conversation && defaultConnector && !isLoading) {
try {
conversation = await createConversation({
apiConfig: {
@ -132,7 +145,6 @@ export const useAssistantOverlay = (
},
category: 'assistant',
title: conversationTitle ?? '',
id: promptContextId,
});
} catch (e) {
/* empty */
@ -151,9 +163,10 @@ export const useAssistantOverlay = (
apiConfig,
assistantContextShowOverlay,
conversationTitle,
conversations,
createConversation,
defaultConnector,
getConversation,
isLoading,
promptContextId,
]
);

View file

@ -58,6 +58,19 @@ export const createConversationRoute = (router: ElasticAssistantPluginRouter): v
});
}
const result = await dataClient?.findDocuments({
perPage: 100,
page: 1,
filter: `users:{ id: "${authenticatedUser?.profile_uid}" } AND title:${request.body.title}`,
fields: ['title'],
});
if (result?.data != null && result.total > 0) {
return assistantResponse.error({
statusCode: 409,
body: `conversation title: "${request.body.title}" already exists`,
});
}
const createdConversation = await dataClient?.createConversation({
conversation: request.body,
authenticatedUser,