This is an automated email from the ASF dual-hosted git repository.

pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 08a558e151 NIFI-14765 Corrected Authorizable Lookup for Nested 
Controller Objects
08a558e151 is described below

commit 08a558e151db0f5f64d77dac4511d078547b10ee
Author: exceptionfactory <[email protected]>
AuthorDate: Fri Jul 18 22:46:25 2025 -0500

    NIFI-14765 Corrected Authorizable Lookup for Nested Controller Objects
    
    - Added Resource Type resolution for Registry Client and Flow Analysis Rule 
components nested under the Controller
    
    Signed-off-by: Pierre Villard <[email protected]>
    
    This closes #10110.
---
 .../authorization/StandardAuthorizableLookup.java  | 17 ++++++
 .../StandardAuthorizableLookupTest.java            | 69 ++++++++++++++++++----
 2 files changed, 73 insertions(+), 13 deletions(-)

diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
index a780e5f22b..ffa8933231 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
@@ -591,6 +591,23 @@ public class StandardAuthorizableLookup implements 
AuthorizableLookup {
                         return new 
OperationAuthorizable(getAccessPolicy(baseResourceType, resource));
                 }
 
+            case Controller:
+                // Handle Nested Resource Types such as Flow Analysis Rules 
and Flow Registry Clients
+                final ResourceType nestedResourceType;
+                if 
(resource.startsWith(ResourceType.RegistryClient.getValue())) {
+                    nestedResourceType = ResourceType.RegistryClient;
+                } else if 
(resource.startsWith(ResourceType.FlowAnalysisRule.getValue())) {
+                    nestedResourceType = ResourceType.FlowAnalysisRule;
+                } else {
+                    nestedResourceType = null;
+                }
+
+                if (nestedResourceType == null) {
+                    return getAccessPolicy(resourceType, resource);
+                } else {
+                    final String componentId = 
StringUtils.substringAfter(resource, 
nestedResourceType.getValue()).substring(1);
+                    return getAccessPolicyByResource(nestedResourceType, 
componentId);
+                }
             case RestrictedComponents:
                 final String slashRequiredPermission = 
StringUtils.substringAfter(resource, resourceType.getValue());
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
index 319b4aab6e..116f55c727 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/authorization/StandardAuthorizableLookupTest.java
@@ -22,13 +22,18 @@ import 
org.apache.nifi.authorization.resource.DataAuthorizable;
 import org.apache.nifi.authorization.resource.DataTransferAuthorizable;
 import org.apache.nifi.authorization.resource.OperationAuthorizable;
 import org.apache.nifi.authorization.resource.ProvenanceDataAuthorizable;
+import org.apache.nifi.controller.FlowAnalysisRuleNode;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.nar.ExtensionDiscoveringManager;
 import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.registry.flow.FlowRegistryClientNode;
 import org.apache.nifi.web.controller.ControllerFacade;
+import org.apache.nifi.web.dao.FlowAnalysisRuleDAO;
+import org.apache.nifi.web.dao.FlowRegistryDAO;
 import org.apache.nifi.web.dao.ProcessorDAO;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -36,20 +41,11 @@ import static org.mockito.Mockito.when;
 
 public class StandardAuthorizableLookupTest {
 
-    @Test
-    public void testGetAuthorizableFromResource() {
-        final ExtensionManager extensionManager = 
mock(ExtensionDiscoveringManager.class);
-        final ControllerFacade controllerFacade = mock(ControllerFacade.class);
-        
when(controllerFacade.getExtensionManager()).thenReturn(extensionManager);
+    private static final String COMPONENT_ID = "id";
 
-        final ProcessorDAO processorDAO = mock(ProcessorDAO.class);
-        final ProcessorNode processorNode = mock(ProcessorNode.class);
-
-        when(processorDAO.getProcessor(eq("id"))).thenReturn(processorNode);
-
-        final StandardAuthorizableLookup lookup = new 
StandardAuthorizableLookup();
-        lookup.setProcessorDAO(processorDAO);
-        lookup.setControllerFacade(controllerFacade);
+    @Test
+    void testGetAuthorizableFromResource() {
+        final StandardAuthorizableLookup lookup = getLookup();
 
         Authorizable authorizable = 
lookup.getAuthorizableFromResource("/processors/id");
         assertInstanceOf(ProcessorNode.class, authorizable);
@@ -74,4 +70,51 @@ public class StandardAuthorizableLookupTest {
         assertInstanceOf(OperationAuthorizable.class, authorizable);
         assertInstanceOf(ProcessorNode.class, ((OperationAuthorizable) 
authorizable).getBaseAuthorizable());
     }
+
+    @Test
+    void testGetAuthorizableFromResourceController() {
+        final StandardAuthorizableLookup lookup = getLookup();
+
+        final Authorizable authorizable = 
lookup.getAuthorizableFromResource("/controller");
+        assertInstanceOf(ControllerFacade.class, authorizable);
+    }
+
+    @Test
+    void testGetAuthorizableFromResourceRegistryClient() {
+        final StandardAuthorizableLookup lookup = getLookup();
+        final FlowRegistryDAO flowRegistryDAO = mock(FlowRegistryDAO.class);
+        final FlowRegistryClientNode flowRegistryClientNode = 
mock(FlowRegistryClientNode.class);
+        
when(flowRegistryDAO.getFlowRegistryClient(eq(COMPONENT_ID))).thenReturn(flowRegistryClientNode);
+        lookup.setFlowRegistryDAO(flowRegistryDAO);
+
+        final Authorizable authorizable = 
lookup.getAuthorizableFromResource("/controller/registry-clients/id");
+        assertEquals(flowRegistryClientNode, authorizable);
+    }
+
+    @Test
+    void testGetAuthorizableFromResourceFlowAnalysisRule() {
+        final StandardAuthorizableLookup lookup = getLookup();
+        final FlowAnalysisRuleDAO flowAnalysisRuleDAO = 
mock(FlowAnalysisRuleDAO.class);
+        final FlowAnalysisRuleNode flowAnalysisRuleNode = 
mock(FlowAnalysisRuleNode.class);
+        
when(flowAnalysisRuleDAO.getFlowAnalysisRule(eq(COMPONENT_ID))).thenReturn(flowAnalysisRuleNode);
+        lookup.setFlowAnalysisRuleDAO(flowAnalysisRuleDAO);
+
+        final Authorizable authorizable = 
lookup.getAuthorizableFromResource("/controller/flow-analysis-rules/id");
+        assertEquals(flowAnalysisRuleNode, authorizable);
+    }
+
+    private StandardAuthorizableLookup getLookup() {
+        final ExtensionManager extensionManager = 
mock(ExtensionDiscoveringManager.class);
+        final ControllerFacade controllerFacade = mock(ControllerFacade.class);
+        
when(controllerFacade.getExtensionManager()).thenReturn(extensionManager);
+
+        final ProcessorDAO processorDAO = mock(ProcessorDAO.class);
+        final ProcessorNode processorNode = mock(ProcessorNode.class);
+        
when(processorDAO.getProcessor(eq(COMPONENT_ID))).thenReturn(processorNode);
+
+        final StandardAuthorizableLookup lookup = new 
StandardAuthorizableLookup();
+        lookup.setProcessorDAO(processorDAO);
+        lookup.setControllerFacade(controllerFacade);
+        return lookup;
+    }
 }

Reply via email to