40
40
import org .opensearch .action .index .IndexResponse ;
41
41
import org .opensearch .action .search .SearchRequest ;
42
42
import org .opensearch .action .search .SearchResponse ;
43
+ import org .opensearch .action .update .UpdateRequest ;
44
+ import org .opensearch .action .update .UpdateResponse ;
43
45
import org .opensearch .client .Client ;
44
46
import org .opensearch .client .Requests ;
45
47
import org .opensearch .cluster .service .ClusterService ;
@@ -330,6 +332,47 @@ public void getTraces(String interactionId, int from, int maxResults, ActionList
330
332
listener .onResponse (List .of ());
331
333
return ;
332
334
}
335
+
336
+ try (ThreadContext .StoredContext threadContext = client .threadPool ().getThreadContext ().stashContext ()) {
337
+ ActionListener <List <Interaction >> internalListener = ActionListener .runBefore (listener , () -> threadContext .restore ());
338
+ GetRequest request = Requests .getRequest (INTERACTIONS_INDEX_NAME ).id (interactionId );
339
+ ActionListener <GetResponse > al = ActionListener .wrap (getResponse -> {
340
+ // If the interaction doesn't exist, fail
341
+ if (!(getResponse .isExists () && getResponse .getId ().equals (interactionId ))) {
342
+ throw new ResourceNotFoundException ("Interaction [" + interactionId + "] not found" );
343
+ }
344
+ Interaction interaction = Interaction .fromMap (interactionId , getResponse .getSourceAsMap ());
345
+ // checks if the user has permission to access the conversation that the interaction belongs to
346
+ String conversationId = interaction .getConversationId ();
347
+ ActionListener <Boolean > accessListener = ActionListener .wrap (access -> {
348
+ if (access ) {
349
+ innerGetTraces (interactionId , from , maxResults , listener );
350
+ } else {
351
+ String userstr = client
352
+ .threadPool ()
353
+ .getThreadContext ()
354
+ .getTransient (ConfigConstants .OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT );
355
+ String user = User .parse (userstr ) == null
356
+ ? ActionConstants .DEFAULT_USERNAME_FOR_ERRORS
357
+ : User .parse (userstr ).getName ();
358
+ throw new OpenSearchSecurityException ("User [" + user + "] does not have access to interaction " + interactionId );
359
+ }
360
+ }, e -> { listener .onFailure (e ); });
361
+ conversationMetaIndex .checkAccess (conversationId , accessListener );
362
+ }, e -> { internalListener .onFailure (e ); });
363
+ client .admin ().indices ().refresh (Requests .refreshRequest (INTERACTIONS_INDEX_NAME ), ActionListener .wrap (refreshResponse -> {
364
+ client .get (request , al );
365
+ }, e -> {
366
+ log .error ("Failed to refresh interactions index during get interaction " , e );
367
+ internalListener .onFailure (e );
368
+ }));
369
+ } catch (Exception e ) {
370
+ listener .onFailure (e );
371
+ }
372
+ }
373
+
374
+ @ VisibleForTesting
375
+ void innerGetTraces (String interactionId , int from , int maxResults , ActionListener <List <Interaction >> listener ) {
333
376
SearchRequest request = Requests .searchRequest (INTERACTIONS_INDEX_NAME );
334
377
// Build the query
335
378
BoolQueryBuilder boolQueryBuilder = QueryBuilders .boolQuery ();
@@ -509,12 +552,13 @@ public void getInteraction(String interactionId, ActionListener<Interaction> lis
509
552
ActionListener <Interaction > internalListener = ActionListener .runBefore (listener , () -> threadContext .restore ());
510
553
GetRequest request = Requests .getRequest (INTERACTIONS_INDEX_NAME ).id (interactionId );
511
554
ActionListener <GetResponse > al = ActionListener .wrap (getResponse -> {
512
- // If the conversation doesn't exist, fail
555
+ // If the interaction doesn't exist, fail
513
556
if (!(getResponse .isExists () && getResponse .getId ().equals (interactionId ))) {
514
557
throw new ResourceNotFoundException ("Interaction [" + interactionId + "] not found" );
515
558
}
516
559
Interaction interaction = Interaction .fromMap (interactionId , getResponse .getSourceAsMap ());
517
- internalListener .onResponse (interaction );
560
+ // checks if the user has permission to access the conversation that the interaction belongs to
561
+ checkInteractionPermission (interactionId , interaction , internalListener );
518
562
}, e -> { internalListener .onFailure (e ); });
519
563
client .admin ().indices ().refresh (Requests .refreshRequest (INTERACTIONS_INDEX_NAME ), ActionListener .wrap (refreshResponse -> {
520
564
client .get (request , al );
@@ -526,4 +570,81 @@ public void getInteraction(String interactionId, ActionListener<Interaction> lis
526
570
listener .onFailure (e );
527
571
}
528
572
}
573
+
574
+ public void updateInteraction (String interactionId , UpdateRequest updateRequest , ActionListener <UpdateResponse > listener ) {
575
+ if (!clusterService .state ().metadata ().hasIndex (INTERACTIONS_INDEX_NAME )) {
576
+ listener
577
+ .onFailure (
578
+ new IndexNotFoundException (
579
+ "cannot update interaction since the interaction index does not exist" ,
580
+ INTERACTIONS_INDEX_NAME
581
+ )
582
+ );
583
+ return ;
584
+ }
585
+
586
+ try (ThreadContext .StoredContext threadContext = client .threadPool ().getThreadContext ().stashContext ()) {
587
+ ActionListener <UpdateResponse > internalListener = ActionListener .runBefore (listener , () -> threadContext .restore ());
588
+ GetRequest request = Requests .getRequest (INTERACTIONS_INDEX_NAME ).id (interactionId );
589
+ ActionListener <GetResponse > al = ActionListener .wrap (getResponse -> {
590
+ // If the interaction doesn't exist, fail
591
+ if (!(getResponse .isExists () && getResponse .getId ().equals (interactionId ))) {
592
+ throw new ResourceNotFoundException ("Interaction [" + interactionId + "] not found" );
593
+ }
594
+ Interaction interaction = Interaction .fromMap (interactionId , getResponse .getSourceAsMap ());
595
+ // checks if the user has permission to access the conversation that the interaction belongs to
596
+ String conversationId = interaction .getConversationId ();
597
+ ActionListener <Boolean > accessListener = ActionListener .wrap (access -> {
598
+ if (access ) {
599
+ innerUpdateInteraction (updateRequest , internalListener );
600
+ } else {
601
+ String userstr = client
602
+ .threadPool ()
603
+ .getThreadContext ()
604
+ .getTransient (ConfigConstants .OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT );
605
+ String user = User .parse (userstr ) == null
606
+ ? ActionConstants .DEFAULT_USERNAME_FOR_ERRORS
607
+ : User .parse (userstr ).getName ();
608
+ throw new OpenSearchSecurityException ("User [" + user + "] does not have access to interaction " + interactionId );
609
+ }
610
+ }, e -> { listener .onFailure (e ); });
611
+ conversationMetaIndex .checkAccess (conversationId , accessListener );
612
+ }, e -> { internalListener .onFailure (e ); });
613
+ client .admin ().indices ().refresh (Requests .refreshRequest (INTERACTIONS_INDEX_NAME ), ActionListener .wrap (refreshResponse -> {
614
+ client .get (request , al );
615
+ }, e -> {
616
+ log .error ("Failed to refresh interactions index during get interaction " , e );
617
+ internalListener .onFailure (e );
618
+ }));
619
+ } catch (Exception e ) {
620
+ listener .onFailure (e );
621
+ }
622
+ }
623
+
624
+ private void innerUpdateInteraction (UpdateRequest updateRequest , ActionListener <UpdateResponse > listener ) {
625
+ try (ThreadContext .StoredContext threadContext = client .threadPool ().getThreadContext ().stashContext ()) {
626
+ ActionListener <UpdateResponse > internalListener = ActionListener .runBefore (listener , () -> threadContext .restore ());
627
+ client .update (updateRequest , internalListener );
628
+ } catch (Exception e ) {
629
+ log .error ("Failed to update Conversation. Details {}:" , e );
630
+ listener .onFailure (e );
631
+ }
632
+ }
633
+
634
+ private void checkInteractionPermission (String interactionId , Interaction interaction , ActionListener <Interaction > internalListener ) {
635
+ String conversationId = interaction .getConversationId ();
636
+ ActionListener <Boolean > accessListener = ActionListener .wrap (access -> {
637
+ if (access ) {
638
+ internalListener .onResponse (interaction );
639
+ } else {
640
+ String userstr = client
641
+ .threadPool ()
642
+ .getThreadContext ()
643
+ .getTransient (ConfigConstants .OPENSEARCH_SECURITY_USER_INFO_THREAD_CONTEXT );
644
+ String user = User .parse (userstr ) == null ? ActionConstants .DEFAULT_USERNAME_FOR_ERRORS : User .parse (userstr ).getName ();
645
+ throw new OpenSearchSecurityException ("User [" + user + "] does not have access to interaction " + interactionId );
646
+ }
647
+ }, e -> { internalListener .onFailure (e ); });
648
+ conversationMetaIndex .checkAccess (conversationId , accessListener );
649
+ }
529
650
}
0 commit comments