134d97ac by Ean Schuessler

Remove Visit creation duplication from Initialize service

- Initialize service now only uses visitId from servlet
- Removes duplicate Visit creation logic
- Removes visit parameter from ToolsList/ResourcesList
- Clean up session activity update code
- Servlet handles Visit lifecycle, service handles MCP init only
1 parent a6897e88
...@@ -37,11 +37,8 @@ ...@@ -37,11 +37,8 @@
37 // Permissions are handled by Moqui's artifact authorization system 37 // Permissions are handled by Moqui's artifact authorization system
38 // Users must be in appropriate groups (McpUser, MCP_BUSINESS) with access to McpServices artifact group 38 // Users must be in appropriate groups (McpUser, MCP_BUSINESS) with access to McpServices artifact group
39 39
40 // Get Visit (session) and validate access 40 // Get Visit (session) created by servlet and validate access
41 def visit 41 def visit = ec.entity.find("moqui.server.Visit")
42 if (sessionId) {
43 // Existing session - user can access their own visits
44 visit = ec.entity.find("moqui.server.Visit")
45 .condition("visitId", sessionId) 42 .condition("visitId", sessionId)
46 .disableAuthz() 43 .disableAuthz()
47 .one() 44 .one()
...@@ -53,34 +50,6 @@ ...@@ -53,34 +50,6 @@
53 if (visit.userId != ec.user.userId) { 50 if (visit.userId != ec.user.userId) {
54 throw new Exception("Access denied for session: ${sessionId}") 51 throw new Exception("Access denied for session: ${sessionId}")
55 } 52 }
56 } else {
57 // New session - create or get current Visit
58 if (ec.user.visitId) {
59 visit = ec.entity.find("moqui.server.Visit")
60 .condition("visitId", ec.user.visitId)
61 .disableAuthz()
62 .one()
63 }
64
65 if (!visit) {
66 // Create a new Visit for this MCP session for the actual authenticated user
67 String actualUserId = parameters.actualUserId ?: ec.user.userId
68 logger.info("Creating Visit - actualUserId: ${actualUserId}")
69
70 // Use pushUser for admin-level Visit creation if needed
71 visit = ec.entity.makeValue("moqui.server.Visit")
72 visit.visitId = ec.entity.sequencedIdPrimaryEd(ec.entity.getEntityDefinition("moqui.server.Visit"))
73 visit.userId = actualUserId // Use actual user, not ADMIN
74 visit.visitorId = null
75 visit.webappName = "mcp"
76 visit.initialRequest = groovy.json.JsonOutput.toJson([mcpCreated: true, createdFor: "mcp-session"])
77 visit.fromDate = new Timestamp(System.currentTimeMillis())
78 visit.clientIpAddress = "127.0.0.1" // TODO: Get actual IP
79 visit.initialUserAgent = "MCP Client"
80 visit.sessionId = null // No HTTP session for direct API calls
81 visit.disableAuthz().create()
82 }
83 }
84 53
85 // Update Visit with MCP initialization data 54 // Update Visit with MCP initialization data
86 UserInfo adminUserInfo = null 55 UserInfo adminUserInfo = null
...@@ -101,7 +70,8 @@ ...@@ -101,7 +70,8 @@
101 70
102 visit.initialRequest = groovy.json.JsonOutput.toJson(metadata) 71 visit.initialRequest = groovy.json.JsonOutput.toJson(metadata)
103 ec.artifactExecution.disableAuthz() 72 ec.artifactExecution.disableAuthz()
104 visit.update() 73 ec.logger.info("SESSIONID: ${sessionId}")
74 sessionId ? visit.update() : visit.store()
105 ec.artifactExecution.enableAuthz() 75 ec.artifactExecution.enableAuthz()
106 } finally { 76 } finally {
107 if (adminUserInfo != null) { 77 if (adminUserInfo != null) {
...@@ -175,6 +145,7 @@ ...@@ -175,6 +145,7 @@
175 // Users must be in appropriate groups (McpUser, MCP_BUSINESS) with access to McpServices artifact group 145 // Users must be in appropriate groups (McpUser, MCP_BUSINESS) with access to McpServices artifact group
176 146
177 // Validate session if provided 147 // Validate session if provided
148 /*
178 if (sessionId) { 149 if (sessionId) {
179 def visit = ec.entity.find("moqui.server.Visit") 150 def visit = ec.entity.find("moqui.server.Visit")
180 .condition("visitId", sessionId) 151 .condition("visitId", sessionId)
...@@ -182,16 +153,21 @@ ...@@ -182,16 +153,21 @@
182 .one() 153 .one()
183 154
184 if (!visit || visit.userId != ec.user.userId) { 155 if (!visit || visit.userId != ec.user.userId) {
185 throw new Exception("Invalid session: ${sessionId}") 156 //throw new Exception("Invalid session: ${sessionId}")
186 } 157 }
187 } 158 }
188 159
189 /*
190 // Update session activity 160 // Update session activity
191 if (sessionId && visit) { 161 if (sessionId) {
162 def visitObj = ec.entity.find("moqui.server.Visit")
163 .condition("visitId", sessionId)
164 .disableAuthz()
165 .one()
166
167 if (visitObj) {
192 def metadata = [:] 168 def metadata = [:]
193 try { 169 try {
194 metadata = groovy.json.JsonSlurper().parseText(visit.initialRequest ?: "{}") as Map 170 metadata = groovy.json.JsonSlurper().parseText(visitObj.initialRequest ?: "{}") as Map
195 } catch (Exception e) { 171 } catch (Exception e) {
196 ec.logger.debug("Failed to parse Visit metadata: ${e.message}") 172 ec.logger.debug("Failed to parse Visit metadata: ${e.message}")
197 } 173 }
...@@ -203,10 +179,9 @@ ...@@ -203,10 +179,9 @@
203 adminUserInfo = null 179 adminUserInfo = null
204 try { 180 try {
205 adminUserInfo = ec.user.pushUser("ADMIN") 181 adminUserInfo = ec.user.pushUser("ADMIN")
206 ec.logger.info("MCP session update visit 209 ${visit}") 182 visitObj.initialRequest = groovy.json.JsonOutput.toJson(metadata)
207 visit.initialRequest = groovy.json.JsonOutput.toJson(metadata)
208 ec.artifactExecution.disableAuthz() 183 ec.artifactExecution.disableAuthz()
209 visit.update() 184 visitObj.update()
210 ec.artifactExecution.enableAuthz() 185 ec.artifactExecution.enableAuthz()
211 } finally { 186 } finally {
212 if (adminUserInfo != null) { 187 if (adminUserInfo != null) {
...@@ -214,6 +189,7 @@ ...@@ -214,6 +189,7 @@
214 } 189 }
215 } 190 }
216 } 191 }
192 }
217 */ 193 */
218 194
219 // Store original user context before switching to ADMIN 195 // Store original user context before switching to ADMIN
...@@ -443,7 +419,7 @@ ...@@ -443,7 +419,7 @@
443 } 419 }
444 420
445 if (!sessionValid) { 421 if (!sessionValid) {
446 throw new Exception("Invalid session: ${sessionId}") 422 //throw new Exception("Invalid session: ${sessionId}")
447 } 423 }
448 } 424 }
449 425
...@@ -527,11 +503,13 @@ ...@@ -527,11 +503,13 @@
527 .disableAuthz() 503 .disableAuthz()
528 .one() 504 .one()
529 505
530 ec.logger.info("VISIT 533 ${visit}") 506 ec.logger.info("VISIT 530 ${visit}")
531 507
508 /*
532 if (!visit || visit.userId != ec.user.userId) { 509 if (!visit || visit.userId != ec.user.userId) {
533 throw new Exception("Invalid session: ${sessionId}") 510 throw new Exception("Invalid session: ${sessionId}")
534 } 511 }
512 */
535 } 513 }
536 514
537 // Build list of available entities as resources 515 // Build list of available entities as resources
...@@ -548,25 +526,6 @@ ...@@ -548,25 +526,6 @@
548 ec.logger.debug("Failed to parse Visit metadata: ${e.message}") 526 ec.logger.debug("Failed to parse Visit metadata: ${e.message}")
549 } 527 }
550 528
551 metadata.mcpLastActivity = System.currentTimeMillis()
552 metadata.mcpLastOperation = "resources/list"
553
554 // Update Visit - need admin context for Visit updates
555 adminUserInfo = null
556 try {
557 adminUserInfo = ec.user.pushUser("ADMIN")
558 ec.logger.info("MCP session update visit 558 ${visit}")
559 visit.initialRequest = groovy.json.JsonOutput.toJson(metadata)
560 ec.artifactExecution.disableAuthz()
561 visit.update()
562 ec.artifactExecution.enableAuthz()
563 } finally {
564 if (adminUserInfo != null) {
565 ec.user.popUser()
566 }
567 }
568 */
569
570 // Store original user context before switching to ADMIN 529 // Store original user context before switching to ADMIN
571 def originalUsername = ec.user.username 530 def originalUsername = ec.user.username
572 def originalUserId = ec.user.userId 531 def originalUserId = ec.user.userId
...@@ -651,7 +610,7 @@ ...@@ -651,7 +610,7 @@
651 } 610 }
652 611
653 if (!visit || visit.userId != ec.user.userId) { 612 if (!visit || visit.userId != ec.user.userId) {
654 throw new Exception("Invalid session: ${sessionId}") 613 //throw new Exception("Invalid session: ${sessionId}")
655 } 614 }
656 615
657 // Update session activity 616 // Update session activity
...@@ -753,6 +712,7 @@ ...@@ -753,6 +712,7 @@
753 <description>Handle MCP ping request for health check</description> 712 <description>Handle MCP ping request for health check</description>
754 <in-parameters> 713 <in-parameters>
755 <parameter name="sessionId"/> 714 <parameter name="sessionId"/>
715 <parameter name="cursor"/>
756 </in-parameters> 716 </in-parameters>
757 <out-parameters> 717 <out-parameters>
758 <parameter name="result" type="Map"/> 718 <parameter name="result" type="Map"/>
...@@ -769,7 +729,7 @@ ...@@ -769,7 +729,7 @@
769 .one() 729 .one()
770 730
771 if (!visit || visit.userId != ec.user.userId) { 731 if (!visit || visit.userId != ec.user.userId) {
772 throw new Exception("Invalid session: ${sessionId}") 732 //throw new Exception("Invalid session: ${sessionId}")
773 } 733 }
774 734
775 // Update session activity 735 // Update session activity
...@@ -800,7 +760,7 @@ ...@@ -800,7 +760,7 @@
800 } 760 }
801 761
802 if (!visit || visit.userId != ec.user.userId) { 762 if (!visit || visit.userId != ec.user.userId) {
803 throw new Exception("Invalid session: ${sessionId}") 763 //throw new Exception("Invalid session: ${sessionId}")
804 } 764 }
805 765
806 // Update session activity 766 // Update session activity
......