This is an automated email from the ASF dual-hosted git repository.
ashishvijaywargiya pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push:
new fbd3e76480 Improved: Authorization enforcement for HumanRes category
tree data access (#1637)
fbd3e76480 is described below
commit fbd3e7648052f32c9a05d3af7ae8cf305dffad95
Author: Krishna Uprit <[email protected]>
AuthorDate: Thu Aug 13 16:20:13 2026 +0530
Improved: Authorization enforcement for HumanRes category tree data access
(#1637)
- The getHRChild request now requires authentication.
- The backing handler additionally verifies that the caller holds the
HUMANRES_VIEW permission before returning any data.
- Unit tests were added covering the denied and allowed cases.
Thank you @Krishnauprit18 for your help in this contribution.
---
.../humanres/config/HumanResErrorUiLabels.xml | 3 +
.../org/apache/ofbiz/humanres/HumanResEvents.java | 11 +++
.../ofbiz/humanres/HumanResEventsTest.groovy | 107 +++++++++++++++++++++
.../webapp/humanres/WEB-INF/controller.xml | 2 +-
4 files changed, 122 insertions(+), 1 deletion(-)
diff --git a/applications/humanres/config/HumanResErrorUiLabels.xml
b/applications/humanres/config/HumanResErrorUiLabels.xml
index 97751c0e8d..cbe8936f21 100644
--- a/applications/humanres/config/HumanResErrorUiLabels.xml
+++ b/applications/humanres/config/HumanResErrorUiLabels.xml
@@ -60,4 +60,7 @@
<property key="HumanResFromDateAlreadyExist">
<value xml:lang="en">This FromDate : ${parameters.estimatedStartDate}
already exist.</value>
</property>
+ <property key="HumanResViewPermissionError">
+ <value xml:lang="en">You do not have permission to view Human
Resources organization data.</value>
+ </property>
</resource>
\ No newline at end of file
diff --git
a/applications/humanres/src/main/java/org/apache/ofbiz/humanres/HumanResEvents.java
b/applications/humanres/src/main/java/org/apache/ofbiz/humanres/HumanResEvents.java
index eaf02c015f..96a68f0825 100644
---
a/applications/humanres/src/main/java/org/apache/ofbiz/humanres/HumanResEvents.java
+++
b/applications/humanres/src/main/java/org/apache/ofbiz/humanres/HumanResEvents.java
@@ -28,6 +28,8 @@ import jakarta.servlet.http.HttpServletResponse;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilGenerics;
+import org.apache.ofbiz.base.util.UtilHttp;
+import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
@@ -36,6 +38,7 @@ import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.party.party.PartyHelper;
+import org.apache.ofbiz.security.Security;
public class HumanResEvents {
private static final String MODULE = HumanResEvents.class.getName();
@@ -43,6 +46,14 @@ public class HumanResEvents {
// Please note : the structure of map in this function is according to the
JSON data map of the jsTree
public static String getChildHRCategoryTree(HttpServletRequest request,
HttpServletResponse response) {
+ Security security = (Security) request.getAttribute("security");
+ if (security == null || !security.hasEntityPermission("HUMANRES",
"_VIEW", request.getSession())) {
+ String errMsg = UtilProperties.getMessage(RES_ERROR,
"HumanResViewPermissionError", UtilHttp.getLocale(request));
+ request.setAttribute("_ERROR_MESSAGE_", errMsg);
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ Debug.logWarning("Unauthorized attempt to access getHRChild by
partyId param [%s]", MODULE, request.getParameter("partyId"));
+ return "error";
+ }
Delegator delegator = (Delegator) request.getAttribute("delegator");
String partyId = request.getParameter("partyId");
String onclickFunction = request.getParameter("onclickFunction");
diff --git
a/applications/humanres/src/test/groovy/org/apache/ofbiz/humanres/HumanResEventsTest.groovy
b/applications/humanres/src/test/groovy/org/apache/ofbiz/humanres/HumanResEventsTest.groovy
new file mode 100644
index 0000000000..16d5a6931e
--- /dev/null
+++
b/applications/humanres/src/test/groovy/org/apache/ofbiz/humanres/HumanResEventsTest.groovy
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+
*******************************************************************************/
+package org.apache.ofbiz.humanres
+
+import static org.mockito.ArgumentMatchers.any
+import static org.mockito.ArgumentMatchers.anyBoolean
+import static org.mockito.ArgumentMatchers.anyString
+import static org.mockito.ArgumentMatchers.eq
+import static org.mockito.Mockito.mock
+import static org.mockito.Mockito.never
+import static org.mockito.Mockito.verify
+import static org.mockito.Mockito.when
+
+import jakarta.servlet.http.HttpServletRequest
+import jakarta.servlet.http.HttpServletResponse
+import jakarta.servlet.http.HttpSession
+
+import org.apache.ofbiz.entity.Delegator
+import org.apache.ofbiz.security.Security
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+/**
+ * Regression tests for the getHRChild fix: {@link
HumanResEvents#getChildHRCategoryTree}
+ * must deny access unless the caller holds HUMANRES_VIEW, and must not query
any
+ * HR/party entities before that check passes.
+ */
+// codenarc-disable JUnitLostTest
+class HumanResEventsTest {
+
+ private HttpServletRequest request
+ private HttpServletResponse response
+ private HttpSession session
+ private Security security
+ private Delegator delegator
+
+ @BeforeEach
+ void setupMocks() {
+ request = mock(HttpServletRequest)
+ response = mock(HttpServletResponse)
+ session = mock(HttpSession)
+ security = mock(Security)
+ delegator = mock(Delegator)
+ when(request.getSession()).thenReturn(session)
+ when(request.getLocale()).thenReturn(Locale.US)
+ }
+
+ @Test
+ void deniesAnonymousCallerWithNoSecurityAttribute() {
+ when(request.getAttribute('security')).thenReturn(null)
+
+ String result = HumanResEvents.getChildHRCategoryTree(request,
response)
+
+ assert result == 'error'
+ verify(response).setStatus(HttpServletResponse.SC_FORBIDDEN)
+ verify(request, never()).setAttribute(eq('hrTree'), any())
+ verify(request, never()).getAttribute('delegator')
+ }
+
+ @Test
+ void deniesAuthenticatedCallerWithoutHumanresViewPermission() {
+ when(request.getAttribute('security')).thenReturn(security)
+ when(security.hasEntityPermission('HUMANRES', '_VIEW',
session)).thenReturn(false)
+
+ String result = HumanResEvents.getChildHRCategoryTree(request,
response)
+
+ assert result == 'error'
+ verify(response).setStatus(HttpServletResponse.SC_FORBIDDEN)
+ verify(request, never()).setAttribute(eq('hrTree'), any())
+ verify(request, never()).getAttribute('delegator')
+ }
+
+ @Test
+ void allowsCallerWithHumanresViewPermissionPastTheGate() {
+ when(request.getAttribute('security')).thenReturn(security)
+ when(request.getAttribute('delegator')).thenReturn(delegator)
+ when(request.getParameter('partyId')).thenReturn('Company')
+ when(security.hasEntityPermission('HUMANRES', '_VIEW',
session)).thenReturn(true)
+ when(delegator.getDelegator()).thenReturn(delegator)
+ when(delegator.findList(anyString(), any(), any(), any(), any(),
any(), anyBoolean()))
+ .thenReturn(Collections.emptyList())
+ when(delegator.findCountByCondition(anyString(), any(), any(), any(),
any())).thenReturn(0L)
+
+ String result = HumanResEvents.getChildHRCategoryTree(request,
response)
+
+ assert result == 'success'
+ verify(response, never()).setStatus(HttpServletResponse.SC_FORBIDDEN)
+ verify(request).setAttribute(eq('hrTree'), any())
+ }
+
+}
diff --git a/applications/humanres/webapp/humanres/WEB-INF/controller.xml
b/applications/humanres/webapp/humanres/WEB-INF/controller.xml
index f446d070f0..d249671eb7 100644
--- a/applications/humanres/webapp/humanres/WEB-INF/controller.xml
+++ b/applications/humanres/webapp/humanres/WEB-INF/controller.xml
@@ -1052,7 +1052,7 @@ under the License.
<response name="error" type="view" value="EditEmplLeaveStatus"/>
</request-map>
<request-map uri="getHRChild">
- <security auth="false" https="true"/>
+ <security auth="true" https="true"/>
<event type="java" path="org.apache.ofbiz.humanres.HumanResEvents"
invoke="getChildHRCategoryTree"/>
<response name="success" type="request" value="json"/>
<response name="error" type="request" value="json"/>