From 82268afb0d9b3fbd7949c430b2cd4be80bdba8c2 Mon Sep 17 00:00:00 2001 From: Matt Gilman Date: Fri, 24 Jun 2016 16:29:00 -0400 Subject: [PATCH] NIFI-1554: - Updating cluster detection to support access through the flow resource. - Using the correct resource when authorizing a root group port during site to site. This closes #579. Signed-off-by: Bryan Bende --- .../web/api/dto/FlowConfigurationDTO.java | 15 +++ .../nifi/remote/StandardRootGroupPort.java | 27 ++-- .../nifi/web/api/ControllerResource.java | 19 --- .../org/apache/nifi/web/api/FlowResource.java | 4 + .../src/main/webapp/js/nf/canvas/nf-canvas.js | 118 ++++++++---------- 5 files changed, 81 insertions(+), 102 deletions(-) diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FlowConfigurationDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FlowConfigurationDTO.java index d5028d254c..668018935e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FlowConfigurationDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/FlowConfigurationDTO.java @@ -33,6 +33,7 @@ public class FlowConfigurationDTO { private Date currentTime; private Integer timeOffset; + private Boolean isClustered; /** * @return interval in seconds between the automatic NiFi refresh requests. This value is read only @@ -77,4 +78,18 @@ public class FlowConfigurationDTO { public void setTimeOffset(Integer timeOffset) { this.timeOffset = timeOffset; } + + /** + * @return whether this NiFi instance is clustered + */ + @ApiModelProperty( + value = "Whether this NiFi instance is clustered." + ) + public Boolean getClustered() { + return isClustered; + } + + public void setClustered(Boolean clustered) { + isClustered = clustered; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java index 9ad9987d3a..b94d86fb5f 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/StandardRootGroupPort.java @@ -16,14 +16,12 @@ */ package org.apache.nifi.remote; +import org.apache.nifi.authorization.AuthorizationRequest; import org.apache.nifi.authorization.AuthorizationResult; import org.apache.nifi.authorization.AuthorizationResult.Result; import org.apache.nifi.authorization.Authorizer; import org.apache.nifi.authorization.RequestAction; -import org.apache.nifi.authorization.Resource; -import org.apache.nifi.authorization.resource.Authorizable; import org.apache.nifi.authorization.resource.ResourceFactory; -import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.connectable.ConnectableType; import org.apache.nifi.controller.AbstractPort; @@ -344,16 +342,6 @@ public class StandardRootGroupPort extends AbstractPort implements RootGroupPort } } - @Override - public Authorizable getParentAuthorizable() { - return null; - } - - @Override - public Resource getResource() { - return ResourceFactory.getSiteToSiteResource(getIdentifier(), getName()); - } - @Override public PortAuthorizationResult checkUserAuthorization(final String dn) { if (!secure) { @@ -367,8 +355,17 @@ public class StandardRootGroupPort extends AbstractPort implements RootGroupPort return new StandardPortAuthorizationResult(false, "User DN is not known"); } - // attempt to authorize the specified user - final AuthorizationResult result = checkAuthorization(authorizer, RequestAction.WRITE, new NiFiUser(dn)); + // build the request + final AuthorizationRequest request = new AuthorizationRequest.Builder() + .identity(dn) + .anonymous(false) + .accessAttempt(true) + .action(RequestAction.WRITE) + .resource(ResourceFactory.getSiteToSiteResource(getIdentifier(), getName())) + .build(); + + // perform the authorization + final AuthorizationResult result = authorizer.authorize(request); if (!Result.Approved.equals(result.getResult())) { final String message = String.format("%s authorization failed for user %s because %s", this, dn, result.getExplanation()); logger.warn(message); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java index bb07751bb5..30cff5f4f8 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerResource.java @@ -58,7 +58,6 @@ import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; -import javax.ws.rs.HEAD; import javax.ws.rs.HttpMethod; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -441,24 +440,6 @@ public class ControllerResource extends ApplicationResource { // cluster // ------- - /** - * Returns a 200 OK response to indicate this is a valid cluster endpoint. - * - * @return An OK response with an empty entity body. - */ - @HEAD - @Consumes(MediaType.WILDCARD) - @Produces(MediaType.WILDCARD) - @Path("cluster") - public Response getClusterHead() { - // TODO - remove once cluster detection is part of /flow - if (isConnectedToCluster()) { - return Response.ok().build(); - } else { - return Response.status(Response.Status.NOT_FOUND).entity("NiFi instance is not clustered").build(); - } - } - /** * Gets the contents of this NiFi cluster. This includes all nodes and their status. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java index e04ed4411c..765933c308 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java @@ -282,6 +282,10 @@ public class FlowResource extends ApplicationResource { } final FlowConfigurationEntity entity = serviceFacade.getFlowConfiguration(); + + // include details about cluster state + entity.getFlowConfiguration().setClustered(isConnectedToCluster()); + return clusterContext(generateOkResponse(entity)).build(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js index d8331cfee0..0724668a2e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas.js @@ -815,24 +815,6 @@ nf.Canvas = (function () { dataType: 'json' }); - // create the deferred cluster request - var isClusteredRequest = $.Deferred(function (deferred) { - $.ajax({ - type: 'HEAD', - url: config.urls.cluster - }).done(function (response, status, xhr) { - clustered = true; - deferred.resolve(response, status, xhr); - }).fail(function (xhr, status, error) { - if (xhr.status === 404) { - clustered = false; - deferred.resolve('', 'success', xhr); - } else { - deferred.reject(xhr, status, error); - } - }); - }).promise(); - // ensure the config requests are loaded $.when(configXhr, userXhr, clientXhr).done(function (configResult, loginResult, aboutResult) { var configResponse = configResult[0]; @@ -844,65 +826,65 @@ nf.Canvas = (function () { // get the config details var configDetails = configResponse.flowConfiguration; - // when both request complete, load the application - isClusteredRequest.done(function () { - // get the auto refresh interval - var autoRefreshIntervalSeconds = parseInt(configDetails.autoRefreshIntervalSeconds, 10); + // update the clustered flag + clustered = configDetails.clustered; - // init storage - nf.Storage.init(); + // get the auto refresh interval + var autoRefreshIntervalSeconds = parseInt(configDetails.autoRefreshIntervalSeconds, 10); - // initialize the application - initCanvas(); - nf.Canvas.View.init(); - nf.ContextMenu.init(); - nf.ng.Bridge.injector.get('headerCtrl').init(); - nf.Settings.init(); - nf.Actions.init(); - nf.QueueListing.init(); - nf.ComponentState.init(); + // init storage + nf.Storage.init(); - // initialize the component behaviors - nf.Draggable.init(); - nf.Selectable.init(); - nf.Connectable.init(); + // initialize the application + initCanvas(); + nf.Canvas.View.init(); + nf.ContextMenu.init(); + nf.ng.Bridge.injector.get('headerCtrl').init(); + nf.Settings.init(); + nf.Actions.init(); + nf.QueueListing.init(); + nf.ComponentState.init(); - // initialize the chart - nf.StatusHistory.init(configDetails.timeOffset); + // initialize the component behaviors + nf.Draggable.init(); + nf.Selectable.init(); + nf.Connectable.init(); - // initialize the birdseye - nf.Birdseye.init(); + // initialize the chart + nf.StatusHistory.init(configDetails.timeOffset); - // initialize components - nf.ConnectionConfiguration.init(); - nf.ControllerService.init(); - nf.ReportingTask.init(); - nf.ProcessorConfiguration.init(); - nf.ProcessGroupConfiguration.init(); - nf.RemoteProcessGroupConfiguration.init(); - nf.RemoteProcessGroupPorts.init(); - nf.PortConfiguration.init(); - nf.LabelConfiguration.init(); - nf.ProcessorDetails.init(); - nf.ProcessGroupDetails.init(); - nf.PortDetails.init(); - nf.ConnectionDetails.init(); - nf.RemoteProcessGroupDetails.init(); - nf.GoTo.init(); - nf.Graph.init().done(function () { - nf.ng.Bridge.injector.get('graphControlsCtrl').init(); + // initialize the birdseye + nf.Birdseye.init(); - // determine the split between the polling - var pollingSplit = autoRefreshIntervalSeconds / 2; + // initialize components + nf.ConnectionConfiguration.init(); + nf.ControllerService.init(); + nf.ReportingTask.init(); + nf.ProcessorConfiguration.init(); + nf.ProcessGroupConfiguration.init(); + nf.RemoteProcessGroupConfiguration.init(); + nf.RemoteProcessGroupPorts.init(); + nf.PortConfiguration.init(); + nf.LabelConfiguration.init(); + nf.ProcessorDetails.init(); + nf.ProcessGroupDetails.init(); + nf.PortDetails.init(); + nf.ConnectionDetails.init(); + nf.RemoteProcessGroupDetails.init(); + nf.GoTo.init(); + nf.Graph.init().done(function () { + nf.ng.Bridge.injector.get('graphControlsCtrl').init(); - // register the polling - setTimeout(function () { - startPolling(autoRefreshIntervalSeconds); - }, pollingSplit * 1000); + // determine the split between the polling + var pollingSplit = autoRefreshIntervalSeconds / 2; - // hide the splash screen - nf.Canvas.hideSplash(); - }).fail(nf.Common.handleAjaxError); + // register the polling + setTimeout(function () { + startPolling(autoRefreshIntervalSeconds); + }, pollingSplit * 1000); + + // hide the splash screen + nf.Canvas.hideSplash(); }).fail(nf.Common.handleAjaxError); }).fail(nf.Common.handleAjaxError); }).fail(nf.Common.handleAjaxError);