@@ -24,6 +24,31 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon
24
24
const retry = getService ( 'retry' ) ;
25
25
const observabilityAIAssistantAPIClient = getService ( 'observabilityAIAssistantApi' ) ;
26
26
27
+ async function getEntries ( {
28
+ query = '' ,
29
+ sortBy = 'title' ,
30
+ sortDirection = 'asc' ,
31
+ spaceId,
32
+ user = 'editor' ,
33
+ } : {
34
+ query ?: string ;
35
+ sortBy ?: string ;
36
+ sortDirection ?: 'asc' | 'desc' ;
37
+ spaceId ?: string ;
38
+ user ?: 'admin' | 'editor' | 'viewer' ;
39
+ } = { } ) : Promise < KnowledgeBaseEntry [ ] > {
40
+ const res = await observabilityAIAssistantAPIClient [ user ] ( {
41
+ endpoint : 'GET /internal/observability_ai_assistant/kb/entries' ,
42
+ params : {
43
+ query : { query, sortBy, sortDirection } ,
44
+ } ,
45
+ spaceId,
46
+ } ) ;
47
+ expect ( res . status ) . to . be ( 200 ) ;
48
+
49
+ return omitCategories ( res . body . entries ) ;
50
+ }
51
+
27
52
describe ( 'Knowledge base' , function ( ) {
28
53
before ( async ( ) => {
29
54
await importTinyElserModel ( ml ) ;
@@ -124,22 +149,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon
124
149
} ) ;
125
150
126
151
describe ( 'when managing multiple entries' , ( ) => {
127
- async function getEntries ( {
128
- query = '' ,
129
- sortBy = 'title' ,
130
- sortDirection = 'asc' ,
131
- } : { query ?: string ; sortBy ?: string ; sortDirection ?: 'asc' | 'desc' } = { } ) {
132
- const res = await observabilityAIAssistantAPIClient . editor ( {
133
- endpoint : 'GET /internal/observability_ai_assistant/kb/entries' ,
134
- params : {
135
- query : { query, sortBy, sortDirection } ,
136
- } ,
137
- } ) ;
138
- expect ( res . status ) . to . be ( 200 ) ;
139
-
140
- return omitCategories ( res . body . entries ) ;
141
- }
142
-
143
152
beforeEach ( async ( ) => {
144
153
await clearKnowledgeBase ( es ) ;
145
154
@@ -200,6 +209,119 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon
200
209
} ) ;
201
210
} ) ;
202
211
212
+ describe ( 'when managing multiple entries across spaces' , ( ) => {
213
+ const SPACE_A_ID = 'space_a' ;
214
+ const SPACE_B_ID = 'space_b' ;
215
+
216
+ before ( async ( ) => {
217
+ await clearKnowledgeBase ( es ) ;
218
+
219
+ const { status : importStatusForSpaceA } = await observabilityAIAssistantAPIClient . admin ( {
220
+ endpoint : 'POST /internal/observability_ai_assistant/kb/entries/import' ,
221
+ params : {
222
+ body : {
223
+ entries : [
224
+ {
225
+ id : 'my-doc-1' ,
226
+ title : `Entry in Space A by Admin 1` ,
227
+ text : `This is a public entry in Space A created by Admin` ,
228
+ public : true ,
229
+ } ,
230
+ {
231
+ id : 'my-doc-2' ,
232
+ title : `Entry in Space A by Admin 2` ,
233
+ text : `This is a private entry in Space A created by Admin` ,
234
+ public : false ,
235
+ } ,
236
+ ] ,
237
+ } ,
238
+ } ,
239
+ spaceId : SPACE_A_ID ,
240
+ } ) ;
241
+ expect ( importStatusForSpaceA ) . to . be ( 200 ) ;
242
+
243
+ const { status : importStatusForSpaceB } = await observabilityAIAssistantAPIClient . admin ( {
244
+ endpoint : 'POST /internal/observability_ai_assistant/kb/entries/import' ,
245
+ params : {
246
+ body : {
247
+ entries : [
248
+ {
249
+ id : 'my-doc-3' ,
250
+ title : `Entry in Space B by Admin 3` ,
251
+ text : `This is a public entry in Space B created by Admin` ,
252
+ public : true ,
253
+ } ,
254
+ {
255
+ id : 'my-doc-4' ,
256
+ title : `Entry in Space B by Admin 4` ,
257
+ text : `This is a private entry in Space B created by Admin` ,
258
+ public : false ,
259
+ } ,
260
+ ] ,
261
+ } ,
262
+ } ,
263
+ spaceId : SPACE_B_ID ,
264
+ } ) ;
265
+ expect ( importStatusForSpaceB ) . to . be ( 200 ) ;
266
+ } ) ;
267
+
268
+ after ( async ( ) => {
269
+ await clearKnowledgeBase ( es ) ;
270
+ } ) ;
271
+
272
+ it ( 'ensures users can only access entries relevant to their namespace' , async ( ) => {
273
+ // User (admin) in space A should only see entries in space A
274
+ const spaceAEntries = await getEntries ( {
275
+ user : 'admin' ,
276
+ spaceId : SPACE_A_ID ,
277
+ } ) ;
278
+
279
+ expect ( spaceAEntries . length ) . to . be ( 2 ) ;
280
+
281
+ expect ( spaceAEntries [ 0 ] . id ) . to . equal ( 'my-doc-1' ) ;
282
+ expect ( spaceAEntries [ 0 ] . public ) . to . be ( true ) ;
283
+ expect ( spaceAEntries [ 0 ] . title ) . to . equal ( 'Entry in Space A by Admin 1' ) ;
284
+
285
+ expect ( spaceAEntries [ 1 ] . id ) . to . equal ( 'my-doc-2' ) ;
286
+ expect ( spaceAEntries [ 1 ] . public ) . to . be ( false ) ;
287
+ expect ( spaceAEntries [ 1 ] . title ) . to . equal ( 'Entry in Space A by Admin 2' ) ;
288
+
289
+ // User (admin) in space B should only see entries in space B
290
+ const spaceBEntries = await getEntries ( {
291
+ user : 'admin' ,
292
+ spaceId : SPACE_B_ID ,
293
+ } ) ;
294
+
295
+ expect ( spaceBEntries . length ) . to . be ( 2 ) ;
296
+
297
+ expect ( spaceBEntries [ 0 ] . id ) . to . equal ( 'my-doc-3' ) ;
298
+ expect ( spaceBEntries [ 0 ] . public ) . to . be ( true ) ;
299
+ expect ( spaceBEntries [ 0 ] . title ) . to . equal ( 'Entry in Space B by Admin 3' ) ;
300
+
301
+ expect ( spaceBEntries [ 1 ] . id ) . to . equal ( 'my-doc-4' ) ;
302
+ expect ( spaceBEntries [ 1 ] . public ) . to . be ( false ) ;
303
+ expect ( spaceBEntries [ 1 ] . title ) . to . equal ( 'Entry in Space B by Admin 4' ) ;
304
+ } ) ;
305
+
306
+ it ( 'should allow a user who is not the owner of the entries to access entries relevant to their namespace' , async ( ) => {
307
+ // User (editor) in space B should only see entries in space B
308
+ const spaceBEntries = await getEntries ( {
309
+ user : 'editor' ,
310
+ spaceId : SPACE_B_ID ,
311
+ } ) ;
312
+
313
+ expect ( spaceBEntries . length ) . to . be ( 2 ) ;
314
+
315
+ expect ( spaceBEntries [ 0 ] . id ) . to . equal ( 'my-doc-3' ) ;
316
+ expect ( spaceBEntries [ 0 ] . public ) . to . be ( true ) ;
317
+ expect ( spaceBEntries [ 0 ] . title ) . to . equal ( 'Entry in Space B by Admin 3' ) ;
318
+
319
+ expect ( spaceBEntries [ 1 ] . id ) . to . equal ( 'my-doc-4' ) ;
320
+ expect ( spaceBEntries [ 1 ] . public ) . to . be ( false ) ;
321
+ expect ( spaceBEntries [ 1 ] . title ) . to . equal ( 'Entry in Space B by Admin 4' ) ;
322
+ } ) ;
323
+ } ) ;
324
+
203
325
describe ( 'security roles and access privileges' , ( ) => {
204
326
describe ( 'should deny access for users without the ai_assistant privilege' , ( ) => {
205
327
it ( 'POST /internal/observability_ai_assistant/kb/entries/save' , async ( ) => {
0 commit comments