1+ package io .sentrius .sso .controllers .api ;
2+
3+ import java .util .HashMap ;
4+ import java .util .List ;
5+ import java .util .Map ;
6+ import com .fasterxml .jackson .databind .JsonNode ;
7+ import com .fasterxml .jackson .databind .ObjectMapper ;
8+ import com .fasterxml .jackson .databind .node .ArrayNode ;
9+ import com .fasterxml .jackson .databind .node .ObjectNode ;
10+ import io .sentrius .sso .core .annotations .LimitAccess ;
11+ import io .sentrius .sso .core .config .SystemOptions ;
12+ import io .sentrius .sso .core .controllers .BaseController ;
13+ import io .sentrius .sso .core .model .security .enums .ApplicationAccessEnum ;
14+ import io .sentrius .sso .core .services .ATPLPolicyService ;
15+ import io .sentrius .sso .core .services .ErrorOutputService ;
16+ import io .sentrius .sso .core .services .UserService ;
17+ import io .sentrius .sso .core .trust .ATPLPolicy ;
18+ import io .sentrius .sso .services .ATPLChatService ;
19+ import jakarta .servlet .http .HttpServletRequest ;
20+ import jakarta .servlet .http .HttpServletResponse ;
21+ import lombok .extern .slf4j .Slf4j ;
22+ import org .springframework .http .ResponseEntity ;
23+ import org .springframework .web .bind .annotation .*;
24+
25+ @ Slf4j
26+ @ RestController
27+ @ RequestMapping ("/api/v1/atpl/chat" )
28+ public class ATPLChatController extends BaseController {
29+
30+ private final ATPLChatService atplChatService ;
31+ private final ATPLPolicyService atplPolicyService ;
32+ private final ObjectMapper objectMapper ;
33+
34+ // Store conversation sessions (in production, use Redis or database)
35+ private final Map <String , Map <String , Object >> chatSessions = new HashMap <>();
36+
37+ public ATPLChatController (
38+ UserService userService ,
39+ SystemOptions systemOptions ,
40+ ErrorOutputService errorOutputService ,
41+ ATPLChatService atplChatService ,
42+ ATPLPolicyService atplPolicyService ,
43+ ObjectMapper objectMapper
44+ ) {
45+ super (userService , systemOptions , errorOutputService );
46+ this .atplChatService = atplChatService ;
47+ this .atplPolicyService = atplPolicyService ;
48+ this .objectMapper = objectMapper ;
49+ }
50+
51+ @ PostMapping ("/message" )
52+ @ LimitAccess (applicationAccess = {ApplicationAccessEnum .CAN_MANAGE_APPLICATION })
53+ public ResponseEntity <ObjectNode > processMessage (
54+ @ RequestBody Map <String , Object > request ,
55+ HttpServletRequest httpRequest ,
56+ HttpServletResponse httpResponse
57+ ) {
58+ try {
59+ String sessionId = (String ) request .get ("sessionId" );
60+ String message = (String ) request .get ("message" );
61+
62+ if (sessionId == null || message == null ) {
63+ return ResponseEntity .badRequest ().body (createErrorResponse ("Session ID and message are required" ));
64+ }
65+
66+ // Get or create session context
67+ Map <String , Object > sessionContext = chatSessions .computeIfAbsent (sessionId , k -> new HashMap <>());
68+
69+ // Process the message with the ATPL chat service
70+ String response = atplChatService .processATPLChatMessage (message , sessionContext );
71+
72+ // Update session context with conversation history
73+ updateSessionContext (sessionContext , message , response );
74+
75+ ObjectNode result = objectMapper .createObjectNode ();
76+ result .put ("response" , response );
77+ result .put ("sessionId" , sessionId );
78+
79+ return ResponseEntity .ok (result );
80+
81+ } catch (Exception e ) {
82+ log .error ("Error processing ATPL chat message: {}" , e .getMessage (), e );
83+ return ResponseEntity .internalServerError ().body (createErrorResponse ("Failed to process message" ));
84+ }
85+ }
86+
87+ @ PostMapping ("/generate-policy" )
88+ @ LimitAccess (applicationAccess = {ApplicationAccessEnum .CAN_MANAGE_APPLICATION })
89+ public ResponseEntity <ObjectNode > generatePolicy (
90+ @ RequestBody Map <String , Object > request ,
91+ HttpServletRequest httpRequest ,
92+ HttpServletResponse httpResponse
93+ ) {
94+ try {
95+ String sessionId = (String ) request .get ("sessionId" );
96+ Map <String , Object > sessionContext = chatSessions .get (sessionId );
97+
98+ if (sessionContext == null ) {
99+ return ResponseEntity .badRequest ().body (createErrorResponse ("Session not found" ));
100+ }
101+
102+ ObjectNode policyNode = atplChatService .generateATPLPolicy (sessionContext );
103+
104+ ObjectNode result = objectMapper .createObjectNode ();
105+ result .set ("policy" , policyNode );
106+ result .put ("sessionId" , sessionId );
107+
108+ return ResponseEntity .ok (result );
109+
110+ } catch (Exception e ) {
111+ log .error ("Error generating ATPL policy: {}" , e .getMessage (), e );
112+ return ResponseEntity .internalServerError ().body (createErrorResponse ("Failed to generate policy" ));
113+ }
114+ }
115+
116+ @ GetMapping ("/suggestions" )
117+ @ LimitAccess (applicationAccess = {ApplicationAccessEnum .CAN_MANAGE_APPLICATION })
118+ public ResponseEntity <ObjectNode > getSuggestions (
119+ @ RequestParam String description ,
120+ HttpServletRequest httpRequest ,
121+ HttpServletResponse httpResponse
122+ ) {
123+ try {
124+ List <String > suggestions = atplChatService .suggestCapabilities (description );
125+
126+ ObjectNode result = objectMapper .createObjectNode ();
127+ ArrayNode suggestionsArray = objectMapper .createArrayNode ();
128+ suggestions .forEach (suggestionsArray ::add );
129+ result .set ("suggestions" , suggestionsArray );
130+
131+ return ResponseEntity .ok (result );
132+
133+ } catch (Exception e ) {
134+ log .error ("Error getting suggestions: {}" , e .getMessage (), e );
135+ return ResponseEntity .internalServerError ().body (createErrorResponse ("Failed to get suggestions" ));
136+ }
137+ }
138+
139+ @ GetMapping ("/existing-policies" )
140+ @ LimitAccess (applicationAccess = {ApplicationAccessEnum .CAN_MANAGE_APPLICATION })
141+ public ResponseEntity <ObjectNode > getExistingPolicies (
142+ HttpServletRequest httpRequest ,
143+ HttpServletResponse httpResponse
144+ ) {
145+ try {
146+ List <ATPLPolicy > policies = atplPolicyService .getAllPolicies ();
147+
148+ ObjectNode result = objectMapper .createObjectNode ();
149+ ArrayNode policiesArray = objectMapper .createArrayNode ();
150+
151+ for (ATPLPolicy policy : policies ) {
152+ ObjectNode policyNode = objectMapper .createObjectNode ();
153+ policyNode .put ("id" , policy .getPolicyId ());
154+ policyNode .put ("description" , policy .getDescription ());
155+ policyNode .put ("version" , policy .getVersion ());
156+
157+ if (policy .getCapabilities () != null && policy .getCapabilities ().getPrimitives () != null ) {
158+ ArrayNode capabilitiesArray = objectMapper .createArrayNode ();
159+ policy .getCapabilities ().getPrimitives ().forEach (cap -> {
160+ ObjectNode capNode = objectMapper .createObjectNode ();
161+ capNode .put ("id" , cap .getId ());
162+ capNode .put ("description" , cap .getDescription ());
163+ capabilitiesArray .add (capNode );
164+ });
165+ policyNode .set ("capabilities" , capabilitiesArray );
166+ }
167+
168+ policiesArray .add (policyNode );
169+ }
170+
171+ result .set ("policies" , policiesArray );
172+ return ResponseEntity .ok (result );
173+
174+ } catch (Exception e ) {
175+ log .error ("Error getting existing policies: {}" , e .getMessage (), e );
176+ return ResponseEntity .internalServerError ().body (createErrorResponse ("Failed to get existing policies" ));
177+ }
178+ }
179+
180+ private void updateSessionContext (Map <String , Object > sessionContext , String userMessage , String agentResponse ) {
181+ // Store conversation history
182+ @ SuppressWarnings ("unchecked" )
183+ List <Map <String , String >> history = (List <Map <String , String >>) sessionContext .computeIfAbsent ("conversation_history" , k -> new java .util .ArrayList <>());
184+
185+ Map <String , String > userEntry = new HashMap <>();
186+ userEntry .put ("type" , "user" );
187+ userEntry .put ("message" , userMessage );
188+ history .add (userEntry );
189+
190+ Map <String , String > agentEntry = new HashMap <>();
191+ agentEntry .put ("type" , "assistant" );
192+ agentEntry .put ("message" , agentResponse );
193+ history .add (agentEntry );
194+
195+ // Keep only last 10 exchanges
196+ if (history .size () > 20 ) {
197+ history .subList (0 , history .size () - 20 ).clear ();
198+ }
199+ }
200+
201+ private ObjectNode createErrorResponse (String message ) {
202+ ObjectNode error = objectMapper .createObjectNode ();
203+ error .put ("error" , message );
204+ return error ;
205+ }
206+ }
0 commit comments