943c1230 by Ean Schuessler

WIP switch to internal permissions

1 parent 48c958e9
...@@ -44,9 +44,10 @@ ...@@ -44,9 +44,10 @@
44 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="McpServices.list#Products" artifactTypeEnumId="AT_SERVICE"/> 44 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="McpServices.list#Products" artifactTypeEnumId="AT_SERVICE"/>
45 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.ledger.LedgerServices.find#GlAccount" artifactTypeEnumId="AT_SERVICE"/> 45 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.ledger.LedgerServices.find#GlAccount" artifactTypeEnumId="AT_SERVICE"/>
46 <!-- Entity Services --> 46 <!-- Entity Services -->
47 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="org.moqui.impl.EntityServices.find#Map" artifactTypeEnumId="AT_SERVICE"/> 47 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="org.moqui.impl.EntityServices.find#Entity" artifactTypeEnumId="AT_SERVICE"/>
48 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="create#moqui.server.Visit" artifactTypeEnumId="AT_SERVICE"/> 48 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="org.moqui.impl.EntityServices.create#Entity" artifactTypeEnumId="AT_SERVICE"/>
49 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="update#moqui.server.Visit" artifactTypeEnumId="AT_SERVICE"/> 49 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="org.moqui.impl.EntityServices.update#Entity" artifactTypeEnumId="AT_SERVICE"/>
50 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="org.moqui.impl.EntityServices.delete#Entity" artifactTypeEnumId="AT_SERVICE"/>
50 51
51 <!-- Essential Business Entities --> 52 <!-- Essential Business Entities -->
52 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.order.OrderHeader" artifactTypeEnumId="AT_ENTITY"/> 53 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.order.OrderHeader" artifactTypeEnumId="AT_ENTITY"/>
...@@ -91,9 +92,4 @@ ...@@ -91,9 +92,4 @@
91 <!-- Add existing demo users to MCP business group for focused testing --> 92 <!-- Add existing demo users to MCP business group for focused testing -->
92 <moqui.security.UserGroupMember userGroupId="MCP_BUSINESS" userId="ORG_ZIZI_JD" fromDate="2025-01-01 00:00:00.000"/> 93 <moqui.security.UserGroupMember userGroupId="MCP_BUSINESS" userId="ORG_ZIZI_JD" fromDate="2025-01-01 00:00:00.000"/>
93 <moqui.security.UserGroupMember userGroupId="MCP_BUSINESS" userId="ORG_ZIZI_BD" fromDate="2025-01-01 00:00:00.000"/> 94 <moqui.security.UserGroupMember userGroupId="MCP_BUSINESS" userId="ORG_ZIZI_BD" fromDate="2025-01-01 00:00:00.000"/>
94
95 <!-- Keep ADMIN access for system operations -->
96 <moqui.security.UserGroupMember userGroupId="ADMIN" userId="MCP_USER" fromDate="2025-01-01 00:00:00.000"/>
97 <moqui.security.UserGroupMember userGroupId="ADMIN" userId="MCP_BUSINESS" fromDate="2025-01-01 00:00:00.000"/>
98
99 </entity-facade-xml> 95 </entity-facade-xml>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -416,20 +416,10 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -416,20 +416,10 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
416 return 416 return
417 } 417 }
418 418
419 // Verify user has access to this Visit - more permissive for testing 419 // Verify user has access to this Visit - rely on Moqui security
420 logger.info("Session validation: visit.userId=${visit.userId}, ec.user.userId=${ec.user.userId}, ec.user.username=${ec.user.username}") 420 logger.info("Session validation: visit.userId=${visit.userId}, ec.user.userId=${ec.user.userId}, ec.user.username=${ec.user.username}")
421 logger.info("DEBUG2: visit.userId exists=${visit.userId != null}, ec.user.userId exists=${ec.user.userId != null}, notEqual=${visit.userId?.toString() != ec.user.userId?.toString()}")
422 if (visit.userId && ec.user.userId && visit.userId.toString() != ec.user.userId.toString()) { 421 if (visit.userId && ec.user.userId && visit.userId.toString() != ec.user.userId.toString()) {
423 logger.warn("Visit userId ${visit.userId} doesn't match current user userId ${ec.user.userId}") 422 logger.warn("Visit userId ${visit.userId} doesn't match current user userId ${ec.user.userId} - access denied")
424
425 // Special case: MCP services run with ADMIN privileges but authenticate as MCP_USER or MCP_BUSINESS
426 boolean specialMcpCase = visit.userId == "ADMIN" && (ec.user.userId == "MCP_USER" || ec.user.userId == "MCP_BUSINESS")
427 logger.info("DEBUG: visit.userId='${visit.userId}' (class: ${visit.userId?.class?.name}), ec.user.userId='${ec.user.userId}' (class: ${ec.user.userId?.class?.name}), specialMcpCase=${specialMcpCase}")
428 if (specialMcpCase) {
429 logger.info("Allowing MCP service access: Visit created with ADMIN, accessed by ${ec.user.userId}")
430 } else if (visit.userCreated == "Y" && ec.user.username) {
431 logger.info("Allowing access for user ${ec.user.username} to Visit ${sessionId}")
432 } else {
433 response.setContentType("application/json") 423 response.setContentType("application/json")
434 response.setCharacterEncoding("UTF-8") 424 response.setCharacterEncoding("UTF-8")
435 response.setStatus(HttpServletResponse.SC_FORBIDDEN) 425 response.setStatus(HttpServletResponse.SC_FORBIDDEN)
...@@ -439,7 +429,6 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -439,7 +429,6 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
439 ])) 429 ]))
440 return 430 return
441 } 431 }
442 }
443 432
444 // Create session wrapper for this Visit 433 // Create session wrapper for this Visit
445 VisitBasedMcpSession session = new VisitBasedMcpSession(visit, response.writer, ec) 434 VisitBasedMcpSession session = new VisitBasedMcpSession(visit, response.writer, ec)
...@@ -689,18 +678,8 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -689,18 +678,8 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
689 // Allow access if: 678 // Allow access if:
690 // 1. Visit userId matches current user, OR 679 // 1. Visit userId matches current user, OR
691 // 2. Visit was created with ADMIN (for privileged access) but current user is MCP_USER (actual authenticated user) 680 // 2. Visit was created with ADMIN (for privileged access) but current user is MCP_USER (actual authenticated user)
692 boolean accessAllowed = false 681 // Rely on Moqui security - only allow access if visit and current user match
693 if (visit.userId && ec.user.userId) { 682 if (!visit.userId || !ec.user.userId || visit.userId.toString() != ec.user.userId.toString()) {
694 if (visit.userId.toString() == ec.user.userId.toString()) {
695 accessAllowed = true
696 } else if (visit.userId.toString() == "ADMIN" && (ec.user.userId.toString() == "MCP_USER" || ec.user.userId.toString() == "MCP_BUSINESS")) {
697 // Special case: MCP services run with ADMIN privileges but authenticate as MCP_USER or MCP_BUSINESS
698 accessAllowed = true
699 logger.info("Allowing MCP privileged access: Visit created with ADMIN, accessed by ${ec.user.userId}")
700 }
701 }
702
703 if (!accessAllowed) {
704 response.setStatus(HttpServletResponse.SC_FORBIDDEN) 683 response.setStatus(HttpServletResponse.SC_FORBIDDEN)
705 response.setContentType("application/json") 684 response.setContentType("application/json")
706 response.writer.write(groovy.json.JsonOutput.toJson([ 685 response.writer.write(groovy.json.JsonOutput.toJson([
......
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!--
3 This software is in the public domain under CC0 1.0 Universal plus a
4 Grant of Patent License.
5
6 To the extent possible under law, author(s) have dedicated all
7 copyright and related and neighboring rights to this software to the
8 public domain worldwide. This software is distributed without any
9 warranty.
10
11 You should have received a copy of the CC0 Public Domain Dedication
12 along with this software (see the LICENSE.md file). If not, see
13 <http://creativecommons.org/publicdomain/zero/1.0/>.
14 -->
15
16 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
17 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
19 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
20 version="4.0">
21
22 <!-- Service-Based MCP Servlet Configuration -->
23 <servlet>
24 <servlet-name>EnhancedMcpServlet</servlet-name>
25 <servlet-class>org.moqui.mcp.EnhancedMcpServlet</servlet-class>
26
27 <init-param>
28 <param-name>keepAliveIntervalSeconds</param-name>
29 <param-value>30</param-value>
30 </init-param>
31 <init-param>
32 <param-name>maxConnections</param-name>
33 <param-value>100</param-value>
34 </init-param>
35
36 <!-- Enable async support for SSE -->
37 <async-supported>true</async-supported>
38
39 <!-- Load on startup -->
40 <load-on-startup>5</load-on-startup>
41 </servlet>
42
43 <servlet-mapping>
44 <servlet-name>EnhancedMcpServlet</servlet-name>
45 <url-pattern>/mcp/*</url-pattern>
46 </servlet-mapping>
47
48 <!-- Session Configuration -->
49 <session-config>
50 <session-timeout>30</session-timeout>
51 <cookie-config>
52 <http-only>true</http-only>
53 <secure>false</secure>
54 </cookie-config>
55 </session-config>
56
57 <!-- Security Constraints (optional - uncomment if needed) -->
58 <!--
59 <security-constraint>
60 <web-resource-collection>
61 <web-resource-name>MCP Endpoints</web-resource-name>
62 <url-pattern>/sse/*</url-pattern>
63 <url-pattern>/mcp/message/*</url-pattern>
64 <url-pattern>/rpc/*</url-pattern>
65 </web-resource-collection>
66 <auth-constraint>
67 <role-name>admin</role-name>
68 </auth-constraint>
69 </security-constraint>
70
71 <login-config>
72 <auth-method>BASIC</auth-method>
73 <realm-name>Moqui MCP</realm-name>
74 </login-config>
75 -->
76
77 <!-- MIME Type Mappings -->
78 <mime-mapping>
79 <extension>json</extension>
80 <mime-type>application/json</mime-type>
81 </mime-mapping>
82
83 <!-- Default Welcome Files -->
84 <welcome-file-list>
85 <welcome-file>index.html</welcome-file>
86 <welcome-file>index.jsp</welcome-file>
87 </welcome-file-list>
88
89 </web-app>