mirror of https://github.com/apache/nifi.git
NIFI-1951:
- Removing deprecated NiFiWebContext and related classes. - Adding authorization to Custom UIs. - Fixing issue when creating ControllerService inline. - Addressing contentType issue when attempting to clear component state. - This closes #489
This commit is contained in:
parent
df0e4e7960
commit
806f4d549d
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* 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.nifi.web;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.nifi.controller.ControllerService;
|
||||
|
||||
/**
|
||||
* NiFi web context providing limited access to dataflow configuration for
|
||||
* processor custom UIs.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface NiFiWebContext {
|
||||
|
||||
/**
|
||||
* @param serviceIdentifier identifier of the service
|
||||
* @return the ControllerService for the specified identifier. If a
|
||||
* corresponding service cannot be found, null is returned. If this NiFi is
|
||||
* clustered, the ControllerService is loaded from the NCM
|
||||
*/
|
||||
ControllerService getControllerService(String serviceIdentifier);
|
||||
|
||||
/**
|
||||
* Provides a mechanism for custom UIs to save actions to appear in NiFi
|
||||
* configuration history. Note all fields within each Action must be
|
||||
* populated. Null values will result in a failure to insert the audit
|
||||
* record. Since the saving to these actions is separate from the actual
|
||||
* configuration change, a failure to insert here will just generate a
|
||||
* warning log message. The recording of these actions typically happens
|
||||
* after a configuration change is applied. Since those changes have already
|
||||
* been applied to the flow, we cannot revert them because of a failure to
|
||||
* insert an audit record.
|
||||
*
|
||||
* @param actions to save
|
||||
*/
|
||||
void saveActions(Collection<ProcessorConfigurationAction> actions);
|
||||
|
||||
/**
|
||||
* @return the current user identity. It may be a dn, an email, a username, or any string that identities the user. Returns null if no user is found
|
||||
*/
|
||||
String getCurrentUserDn();
|
||||
|
||||
/**
|
||||
* @return the current user name. Returns null if no user is found
|
||||
*/
|
||||
String getCurrentUserName();
|
||||
|
||||
/**
|
||||
* Gets the Processor configuration. The given configuration is expected to
|
||||
* contain the following configuration:
|
||||
*
|
||||
* <ul>
|
||||
* <li>revision -- the client identifier and optionally the version
|
||||
* number</li>
|
||||
* <li>processorId -- the id of the processor to retrieve information
|
||||
* for</li>
|
||||
* <li>X509Certificate -- the certificate if this is a secure request</li>
|
||||
* </ul>
|
||||
*
|
||||
* When operating in a clustered environment, if the configuration contains
|
||||
* a X509Certificate, then the certificate information will be forwarded to
|
||||
* the nodes.
|
||||
*
|
||||
* @param config the configuration
|
||||
* @return the processor info object
|
||||
* @throws ResourceNotFoundException if the processor does not exit
|
||||
* @throws ClusterRequestException if the processor was unable to be
|
||||
* retrieved from the cluster. This exception will only be thrown when
|
||||
* operating in a cluster.
|
||||
*/
|
||||
ProcessorInfo getProcessor(NiFiWebContextConfig config) throws ResourceNotFoundException, ClusterRequestException;
|
||||
|
||||
/**
|
||||
* Sets the Processor annotation data. The given configuration is expected
|
||||
* to contain the following configuration:
|
||||
*
|
||||
* <ul>
|
||||
* <li>revision -- the client identifier and optionally the version
|
||||
* number</li>
|
||||
* <li>processorId -- the id of the processor to retrieve information
|
||||
* for</li>
|
||||
* <li>X509Certificate -- the certificate if this is a secure request</li>
|
||||
* </ul>
|
||||
*
|
||||
* When operating in a clustered environment, if the configuration contains
|
||||
* a X509Certificate, then the certificate information will be forwarded to
|
||||
* the nodes.
|
||||
*
|
||||
* @param config the configuration
|
||||
* @param annotationData the annotation data
|
||||
* @throws ResourceNotFoundException if the processor does not exit
|
||||
* @throws InvalidRevisionException if a revision other than the current
|
||||
* revision is given
|
||||
* @throws ClusterRequestException if the annotation data was unable to be
|
||||
* set for the processor. This exception will only be thrown when operating
|
||||
* in a cluster.
|
||||
*/
|
||||
void setProcessorAnnotationData(NiFiWebContextConfig config, String annotationData)
|
||||
throws ResourceNotFoundException, InvalidRevisionException, ClusterRequestException;
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* 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.nifi.web;
|
||||
|
||||
/**
|
||||
* Context configuration for methods invoked from the NiFiWebContext.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface NiFiWebContextConfig {
|
||||
|
||||
/**
|
||||
* The request protocol scheme (http or https). When scheme is https, the
|
||||
* X509Certificate can be used for subsequent remote requests.
|
||||
*
|
||||
* @return the protocol scheme
|
||||
*/
|
||||
String getScheme();
|
||||
|
||||
/**
|
||||
* @return the processor ID
|
||||
*/
|
||||
String getProcessorId();
|
||||
|
||||
/**
|
||||
* @return the revision
|
||||
*/
|
||||
Revision getRevision();
|
||||
|
||||
/**
|
||||
* Returns the proxied entities chain. The format of the chain is as
|
||||
* follows:
|
||||
*
|
||||
* <code>
|
||||
* <CN=original-proxied-entity><CN=first-proxy><CN=second-proxy>...
|
||||
* </code>
|
||||
*
|
||||
* @return the proxied entities chain or null if no chain
|
||||
*/
|
||||
String getProxiedEntitiesChain();
|
||||
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* 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.nifi.web;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class ProcessorConfigurationAction {
|
||||
|
||||
private final String processorId;
|
||||
private final String processorName;
|
||||
private final String processorType;
|
||||
private final String name;
|
||||
private final String previousValue;
|
||||
private final String value;
|
||||
|
||||
private ProcessorConfigurationAction(final Builder builder) {
|
||||
this.processorId = builder.processorId;
|
||||
this.processorName = builder.processorName;
|
||||
this.processorType = builder.processorType;
|
||||
this.name = builder.name;
|
||||
this.previousValue = builder.previousValue;
|
||||
this.value = builder.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id of the processor
|
||||
*/
|
||||
public String getProcessorId() {
|
||||
return processorId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the processor being modified
|
||||
*/
|
||||
public String getProcessorName() {
|
||||
return processorName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of the processor being modified
|
||||
*/
|
||||
public String getProcessorType() {
|
||||
return processorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the field, property, etc that has been modified.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the previous value
|
||||
*/
|
||||
public String getPreviousValue() {
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the new value
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private String processorId;
|
||||
private String processorName;
|
||||
private String processorType;
|
||||
private String name;
|
||||
private String previousValue;
|
||||
private String value;
|
||||
|
||||
public Builder processorId(final String processorId) {
|
||||
this.processorId = processorId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder processorName(final String processorName) {
|
||||
this.processorName = processorName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder processorType(final String processorType) {
|
||||
this.processorType = processorType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder previousValue(final String previousValue) {
|
||||
this.previousValue = previousValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder value(final String value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProcessorConfigurationAction build() {
|
||||
return new ProcessorConfigurationAction(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* 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.nifi.web;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class ProcessorInfo {
|
||||
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final String state;
|
||||
private final String annotationData;
|
||||
private final Map<String, String> properties;
|
||||
private final Collection<String> validationErrors;
|
||||
|
||||
private ProcessorInfo(final Builder builder) {
|
||||
this.id = builder.id;
|
||||
this.name = builder.name;
|
||||
this.state = builder.state;
|
||||
this.annotationData = builder.annotationData;
|
||||
this.properties = builder.properties;
|
||||
this.validationErrors = builder.validationErrors;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public String getAnnotationData() {
|
||||
return annotationData;
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public Collection<String> getValidationErrors() {
|
||||
return validationErrors;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private String state;
|
||||
private String annotationData;
|
||||
private Map<String, String> properties;
|
||||
private Collection<String> validationErrors;
|
||||
|
||||
public Builder id(final String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder state(final String state) {
|
||||
this.state = state;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder annotationData(final String annotationData) {
|
||||
this.annotationData = annotationData;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder properties(final Map<String, String> properties) {
|
||||
this.properties = properties;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder validateErrors(final Collection<String> validationErrors) {
|
||||
this.validationErrors = validationErrors;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProcessorInfo build() {
|
||||
return new ProcessorInfo(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* 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.nifi.web;
|
||||
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* An implementation of the NiFiWebContextConfig that retrieves configuration
|
||||
* from a HttpServletRequest instance.
|
||||
*/
|
||||
@Deprecated
|
||||
public class HttpServletRequestContextConfig implements NiFiWebContextConfig {
|
||||
|
||||
public static final String PROCESSOR_ID_PARAM = "processorId";
|
||||
|
||||
public static final String CLIENT_ID_PARAM = "clientId";
|
||||
|
||||
public static final String REVISION_PARAM = "revision";
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
public HttpServletRequestContextConfig(final HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProxiedEntitiesChain() {
|
||||
|
||||
String xProxiedEntitiesChain = request.getHeader("X-ProxiedEntitiesChain");
|
||||
final X509Certificate cert = extractClientCertificate(request);
|
||||
if (cert != null) {
|
||||
final String extractedPrincipal = extractPrincipal(cert);
|
||||
final String formattedPrincipal = formatProxyDn(extractedPrincipal);
|
||||
if (xProxiedEntitiesChain == null || xProxiedEntitiesChain.trim().isEmpty()) {
|
||||
xProxiedEntitiesChain = formattedPrincipal;
|
||||
} else {
|
||||
xProxiedEntitiesChain += formattedPrincipal;
|
||||
}
|
||||
}
|
||||
|
||||
return xProxiedEntitiesChain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the protocol scheme of the HttpServletRequest instance.
|
||||
*/
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return request.getScheme();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the processor ID retrieved from the request parameter with key
|
||||
* equal to "processorId".
|
||||
*/
|
||||
@Override
|
||||
public String getProcessorId() {
|
||||
return request.getParameter(PROCESSOR_ID_PARAM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the revision retrieved from the request parameters with keys
|
||||
* equal to "clientId" and "revision".
|
||||
*/
|
||||
@Override
|
||||
public Revision getRevision() {
|
||||
|
||||
final String revisionParamVal = request.getParameter(REVISION_PARAM);
|
||||
Long revision;
|
||||
try {
|
||||
revision = Long.parseLong(revisionParamVal);
|
||||
} catch (final Exception ex) {
|
||||
revision = null;
|
||||
}
|
||||
|
||||
final String clientId = request.getParameter(CLIENT_ID_PARAM);
|
||||
|
||||
return new Revision(revision, clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility methods that have been copied into this class to reduce the
|
||||
* dependency footprint of this artifact. These utility methods typically
|
||||
* live in web-utilities but that would pull in spring, jersey, jackson,
|
||||
* etc.
|
||||
*/
|
||||
private X509Certificate extractClientCertificate(HttpServletRequest request) {
|
||||
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
|
||||
|
||||
if (certs != null && certs.length > 0) {
|
||||
return certs[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String extractPrincipal(X509Certificate cert) {
|
||||
return cert.getSubjectDN().getName().trim();
|
||||
}
|
||||
|
||||
private String formatProxyDn(String dn) {
|
||||
return "<" + dn + ">";
|
||||
}
|
||||
}
|
|
@ -58,7 +58,6 @@ import org.apache.nifi.ui.extension.UiExtensionMapping;
|
|||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.web.ContentAccess;
|
||||
import org.apache.nifi.web.NiFiWebConfigurationContext;
|
||||
import org.apache.nifi.web.NiFiWebContext;
|
||||
import org.apache.nifi.web.UiExtensionType;
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -121,9 +120,6 @@ public class JettyServer implements NiFiServer {
|
|||
private UiExtensionMapping componentUiExtensions;
|
||||
private Collection<WebAppContext> componentUiExtensionWebContexts;
|
||||
|
||||
@Deprecated
|
||||
private Collection<WebAppContext> customUiWebContexts;
|
||||
|
||||
/**
|
||||
* Creates and configures a new Jetty instance.
|
||||
*
|
||||
|
@ -222,29 +218,21 @@ public class JettyServer implements NiFiServer {
|
|||
final ClassLoader frameworkClassLoader = getClass().getClassLoader();
|
||||
final ClassLoader jettyClassLoader = frameworkClassLoader.getParent();
|
||||
|
||||
@Deprecated
|
||||
final Map<String, String> customUiMappings = new HashMap<>();
|
||||
|
||||
// deploy the other wars
|
||||
if (CollectionUtils.isNotEmpty(otherWars)) {
|
||||
// hold onto to the web contexts for all ui extensions
|
||||
customUiWebContexts = new ArrayList<>();
|
||||
componentUiExtensionWebContexts = new ArrayList<>();
|
||||
contentViewerWebContexts = new ArrayList<>();
|
||||
|
||||
// ui extension organized by component type
|
||||
final Map<String, List<UiExtension>> componentUiExtensionsByType = new HashMap<>();
|
||||
for (File war : otherWars) {
|
||||
// see if this war is a custom processor ui
|
||||
@Deprecated
|
||||
List<String> customUiProcessorTypes = getWarExtensions(war, "META-INF/nifi-processor");
|
||||
|
||||
// identify all known extension types in the war
|
||||
final Map<UiExtensionType, List<String>> uiExtensionInWar = new HashMap<>();
|
||||
identifyUiExtensionsForComponents(uiExtensionInWar, war);
|
||||
|
||||
// only include wars that are for custom processor ui's
|
||||
if (!customUiProcessorTypes.isEmpty() || !uiExtensionInWar.isEmpty()) {
|
||||
if (!uiExtensionInWar.isEmpty()) {
|
||||
// get the context path
|
||||
String warName = StringUtils.substringBeforeLast(war.getName(), ".");
|
||||
String warContextPath = String.format("/%s", warName);
|
||||
|
@ -260,52 +248,41 @@ public class JettyServer implements NiFiServer {
|
|||
// create the extension web app context
|
||||
WebAppContext extensionUiContext = loadWar(war, warContextPath, narClassLoaderForWar);
|
||||
|
||||
// also store it by type so we can populate the appropriate initialization parameters
|
||||
if (!customUiProcessorTypes.isEmpty()) {
|
||||
customUiWebContexts.add(extensionUiContext);
|
||||
// create the ui extensions
|
||||
for (final Map.Entry<UiExtensionType, List<String>> entry : uiExtensionInWar.entrySet()) {
|
||||
final UiExtensionType extensionType = entry.getKey();
|
||||
final List<String> types = entry.getValue();
|
||||
|
||||
// @Deprecated - supported custom uis as init params to the web api
|
||||
for (String customUiProcessorType : customUiProcessorTypes) {
|
||||
// map the processor type to the custom ui path
|
||||
customUiMappings.put(customUiProcessorType, warContextPath);
|
||||
}
|
||||
} else {
|
||||
// create the ui extensions
|
||||
for (final Map.Entry<UiExtensionType, List<String>> entry : uiExtensionInWar.entrySet()) {
|
||||
final UiExtensionType extensionType = entry.getKey();
|
||||
final List<String> types = entry.getValue();
|
||||
|
||||
if (UiExtensionType.ContentViewer.equals(extensionType)) {
|
||||
// consider each content type identified
|
||||
for (final String contentType : types) {
|
||||
// map the content type to the context path
|
||||
mimeMappings.put(contentType, warContextPath);
|
||||
}
|
||||
|
||||
// this ui extension provides a content viewer
|
||||
contentViewerWebContexts.add(extensionUiContext);
|
||||
} else {
|
||||
// consider each component type identified
|
||||
for (final String componentType : types) {
|
||||
logger.info(String.format("Loading UI extension [%s, %s] for %s", extensionType, warContextPath, types));
|
||||
|
||||
// record the extension definition
|
||||
final UiExtension uiExtension = new UiExtension(extensionType, warContextPath);
|
||||
|
||||
// create if this is the first extension for this component type
|
||||
List<UiExtension> componentUiExtensionsForType = componentUiExtensionsByType.get(componentType);
|
||||
if (componentUiExtensionsForType == null) {
|
||||
componentUiExtensionsForType = new ArrayList<>();
|
||||
componentUiExtensionsByType.put(componentType, componentUiExtensionsForType);
|
||||
}
|
||||
|
||||
// record this extension
|
||||
componentUiExtensionsForType.add(uiExtension);
|
||||
}
|
||||
|
||||
// this ui extension provides a component custom ui
|
||||
componentUiExtensionWebContexts.add(extensionUiContext);
|
||||
if (UiExtensionType.ContentViewer.equals(extensionType)) {
|
||||
// consider each content type identified
|
||||
for (final String contentType : types) {
|
||||
// map the content type to the context path
|
||||
mimeMappings.put(contentType, warContextPath);
|
||||
}
|
||||
|
||||
// this ui extension provides a content viewer
|
||||
contentViewerWebContexts.add(extensionUiContext);
|
||||
} else {
|
||||
// consider each component type identified
|
||||
for (final String componentType : types) {
|
||||
logger.info(String.format("Loading UI extension [%s, %s] for %s", extensionType, warContextPath, types));
|
||||
|
||||
// record the extension definition
|
||||
final UiExtension uiExtension = new UiExtension(extensionType, warContextPath);
|
||||
|
||||
// create if this is the first extension for this component type
|
||||
List<UiExtension> componentUiExtensionsForType = componentUiExtensionsByType.get(componentType);
|
||||
if (componentUiExtensionsForType == null) {
|
||||
componentUiExtensionsForType = new ArrayList<>();
|
||||
componentUiExtensionsByType.put(componentType, componentUiExtensionsForType);
|
||||
}
|
||||
|
||||
// record this extension
|
||||
componentUiExtensionsForType.add(uiExtension);
|
||||
}
|
||||
|
||||
// this ui extension provides a component custom ui
|
||||
componentUiExtensionWebContexts.add(extensionUiContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +303,6 @@ public class JettyServer implements NiFiServer {
|
|||
|
||||
// load the web api app
|
||||
webApiContext = loadWar(webApiWar, "/nifi-api", frameworkClassLoader);
|
||||
webApiContext.getInitParams().putAll(customUiMappings);
|
||||
handlers.addHandler(webApiContext);
|
||||
|
||||
// load the content viewer app
|
||||
|
@ -696,23 +672,6 @@ public class JettyServer implements NiFiServer {
|
|||
// get the application context
|
||||
final WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(webApiServletContext);
|
||||
|
||||
// @Deprecated
|
||||
if (CollectionUtils.isNotEmpty(customUiWebContexts)) {
|
||||
final NiFiWebContext niFiWebContext = webApplicationContext.getBean("nifiWebContext", NiFiWebContext.class);
|
||||
|
||||
for (final WebAppContext customUiContext : customUiWebContexts) {
|
||||
// set the NiFi context in each custom ui servlet context
|
||||
final ServletContext customUiServletContext = customUiContext.getServletHandler().getServletContext();
|
||||
customUiServletContext.setAttribute("nifi-web-context", niFiWebContext);
|
||||
|
||||
// add the security filter to any custom ui wars
|
||||
final FilterHolder securityFilter = webApiContext.getServletHandler().getFilter("springSecurityFilterChain");
|
||||
if (securityFilter != null) {
|
||||
customUiContext.addFilter(securityFilter, "/*", EnumSet.allOf(DispatcherType.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// component ui extensions
|
||||
if (CollectionUtils.isNotEmpty(componentUiExtensionWebContexts)) {
|
||||
final NiFiWebConfigurationContext configurationContext = webApplicationContext.getBean("nifiWebConfigurationContext", NiFiWebConfigurationContext.class);
|
||||
|
|
|
@ -16,28 +16,7 @@
|
|||
*/
|
||||
package org.apache.nifi.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.action.Action;
|
||||
import org.apache.nifi.action.Component;
|
||||
|
@ -194,6 +173,27 @@ import org.apache.nifi.web.util.SnippetUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Implementation of NiFiServiceFacade that performs revision checking.
|
||||
*/
|
||||
|
@ -1612,6 +1612,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
|
||||
@Override
|
||||
public ControllerServiceEntity createControllerService(final String groupId, final ControllerServiceDTO controllerServiceDTO) {
|
||||
// TODO - update once Controller Services can be scoped by Controller
|
||||
final String normalizedGroupId = groupId == null ? controllerFacade.getRootGroupId() : groupId;
|
||||
controllerServiceDTO.setParentGroupId(normalizedGroupId);
|
||||
|
||||
|
@ -1721,12 +1722,15 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
* @param reference ControllerServiceReference
|
||||
* @return The entity
|
||||
*/
|
||||
private ControllerServiceReferencingComponentsEntity createControllerServiceReferencingComponentsEntity(final ControllerServiceReference reference) {
|
||||
private ControllerServiceReferencingComponentsEntity createControllerServiceReferencingComponentsEntity(final ControllerServiceReference reference, final Set<String> lockedIds) {
|
||||
final Set<String> referencingIds = new HashSet<>();
|
||||
final Set<ControllerServiceNode> visited = new HashSet<>();
|
||||
visited.add(reference.getReferencedComponent());
|
||||
findControllerServiceReferencingComponentIdentifiers(reference, referencingIds, visited);
|
||||
|
||||
// TODO remove once we can update a read lock
|
||||
referencingIds.removeAll(lockedIds);
|
||||
|
||||
return revisionManager.get(referencingIds, () -> {
|
||||
final Map<String, Revision> referencingRevisions = new HashMap<>();
|
||||
for (final ConfiguredComponent component : reference.getReferencingComponents()) {
|
||||
|
@ -2614,8 +2618,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
final Set<ControllerServiceNode> serviceNodes;
|
||||
final Set<String> serviceIds;
|
||||
if (groupId == null) {
|
||||
// TODO - controller services scoped by the controller
|
||||
serviceNodes = controllerServiceDAO.getControllerServices();
|
||||
// TODO - update when controller services are scoped by the controller
|
||||
final ProcessGroup group = processGroupDAO.getProcessGroup(controllerFacade.getRootGroupId());
|
||||
serviceNodes = group.getControllerServices(true);
|
||||
serviceIds = serviceNodes.stream().map(service -> service.getIdentifier()).collect(Collectors.toSet());
|
||||
} else {
|
||||
final ProcessGroup group = processGroupDAO.getProcessGroup(groupId);
|
||||
|
@ -2629,7 +2634,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
final ControllerServiceDTO dto = dtoFactory.createControllerServiceDto(serviceNode);
|
||||
|
||||
final ControllerServiceReference ref = serviceNode.getReferences();
|
||||
final ControllerServiceReferencingComponentsEntity referencingComponentsEntity = createControllerServiceReferencingComponentsEntity(ref);
|
||||
final ControllerServiceReferencingComponentsEntity referencingComponentsEntity = createControllerServiceReferencingComponentsEntity(ref, serviceIds);
|
||||
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
|
||||
|
||||
final RevisionDTO revision = dtoFactory.createRevisionDTO(revisionManager.getRevision(serviceNode.getIdentifier()));
|
||||
|
@ -2651,7 +2656,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
final ControllerServiceDTO dto = dtoFactory.createControllerServiceDto(controllerService);
|
||||
|
||||
final ControllerServiceReference ref = controllerService.getReferences();
|
||||
final ControllerServiceReferencingComponentsEntity referencingComponentsEntity = createControllerServiceReferencingComponentsEntity(ref);
|
||||
final ControllerServiceReferencingComponentsEntity referencingComponentsEntity = createControllerServiceReferencingComponentsEntity(ref, Sets.newHashSet(controllerServiceId));
|
||||
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
|
||||
|
||||
return entityFactory.createControllerServiceEntity(dto, revision, accessPolicy);
|
||||
|
@ -2678,7 +2683,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return revisionManager.get(controllerServiceId, rev -> {
|
||||
final ControllerServiceNode service = controllerServiceDAO.getControllerService(controllerServiceId);
|
||||
final ControllerServiceReference ref = service.getReferences();
|
||||
return createControllerServiceReferencingComponentsEntity(ref);
|
||||
return createControllerServiceReferencingComponentsEntity(ref, Sets.newHashSet(controllerServiceId));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,14 @@ import org.apache.nifi.action.Operation;
|
|||
import org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
|
||||
import org.apache.nifi.action.details.FlowChangeConfigureDetails;
|
||||
import org.apache.nifi.admin.service.AuditService;
|
||||
import org.apache.nifi.authorization.AccessDeniedException;
|
||||
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.Authorizable;
|
||||
import org.apache.nifi.authorization.resource.ResourceFactory;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserDetails;
|
||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||
|
@ -74,8 +82,6 @@ import com.sun.jersey.core.util.MultivaluedMapImpl;
|
|||
public class StandardNiFiWebConfigurationContext implements NiFiWebConfigurationContext {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StandardNiFiWebConfigurationContext.class);
|
||||
public static final String CLIENT_ID_PARAM = "clientId";
|
||||
public static final String REVISION_PARAM = "revision";
|
||||
public static final String VERBOSE_PARAM = "verbose";
|
||||
|
||||
private NiFiProperties properties;
|
||||
|
@ -85,15 +91,35 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
private ControllerServiceLookup controllerServiceLookup;
|
||||
private ReportingTaskProvider reportingTaskProvider;
|
||||
private AuditService auditService;
|
||||
private Authorizer authorizer;
|
||||
|
||||
private void authorizeFlowAccess(final NiFiUser user) {
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final AuthorizationRequest request = new AuthorizationRequest.Builder()
|
||||
.resource(ResourceFactory.getFlowResource())
|
||||
.identity(user.getIdentity())
|
||||
.anonymous(user.isAnonymous())
|
||||
.accessAttempt(true)
|
||||
.action(RequestAction.READ)
|
||||
.build();
|
||||
|
||||
final AuthorizationResult result = authorizer.authorize(request);
|
||||
if (!Result.Approved.equals(result.getResult())) {
|
||||
final String message = StringUtils.isNotBlank(result.getExplanation()) ? result.getExplanation() : "Access is denied";
|
||||
throw new AccessDeniedException(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public ControllerService getControllerService(String serviceIdentifier) {
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
authorizeFlowAccess(user);
|
||||
return controllerServiceLookup.getControllerService(serviceIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')")
|
||||
public void saveActions(final NiFiWebRequestContext requestContext, final Collection<ConfigurationAction> configurationActions) {
|
||||
Objects.requireNonNull(configurationActions, "Actions cannot be null.");
|
||||
|
||||
|
@ -105,12 +131,30 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
Component componentType = null;
|
||||
switch (requestContext.getExtensionType()) {
|
||||
case ProcessorConfiguration:
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getProcessor(requestContext.getId());
|
||||
authorizable.authorize(authorizer, RequestAction.WRITE);
|
||||
});
|
||||
|
||||
componentType = Component.Processor;
|
||||
break;
|
||||
case ControllerServiceConfiguration:
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getControllerService(requestContext.getId());
|
||||
authorizable.authorize(authorizer, RequestAction.WRITE);
|
||||
});
|
||||
|
||||
componentType = Component.ControllerService;
|
||||
break;
|
||||
case ReportingTaskConfiguration:
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getReportingTask(requestContext.getId());
|
||||
authorizable.authorize(authorizer, RequestAction.WRITE);
|
||||
});
|
||||
|
||||
componentType = Component.ReportingTask;
|
||||
break;
|
||||
}
|
||||
|
@ -159,33 +203,20 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public String getCurrentUserDn() {
|
||||
String userIdentity = NiFiUser.ANONYMOUS.getIdentity();
|
||||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
if (user != null) {
|
||||
userIdentity = user.getIdentity();
|
||||
}
|
||||
|
||||
return userIdentity;
|
||||
authorizeFlowAccess(user);
|
||||
return user.getIdentity();
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public String getCurrentUserName() {
|
||||
String userName = NiFiUser.ANONYMOUS.getIdentity();
|
||||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
if (user != null) {
|
||||
userName = user.getUserName();
|
||||
}
|
||||
|
||||
return userName;
|
||||
authorizeFlowAccess(user);
|
||||
return user.getUserName();
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) throws ResourceNotFoundException, ClusterRequestException {
|
||||
final String id = requestContext.getId();
|
||||
|
||||
|
@ -220,7 +251,6 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')")
|
||||
public ComponentDetails setAnnotationData(final NiFiWebConfigurationRequestContext requestContext, final String annotationData)
|
||||
throws ResourceNotFoundException, InvalidRevisionException, ClusterRequestException {
|
||||
|
||||
|
@ -288,6 +318,12 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) {
|
||||
final String id = requestContext.getId();
|
||||
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getProcessor(id);
|
||||
authorizable.authorize(authorizer, RequestAction.READ);
|
||||
});
|
||||
|
||||
final ProcessorDTO processor;
|
||||
if (properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
|
||||
// create the request URL
|
||||
|
@ -330,9 +366,16 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
|
||||
@Override
|
||||
public ComponentDetails setAnnotationData(final NiFiWebConfigurationRequestContext requestContext, final String annotationData) {
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
final Revision revision = requestContext.getRevision();
|
||||
final String id = requestContext.getId();
|
||||
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getProcessor(id);
|
||||
authorizable.authorize(authorizer, RequestAction.WRITE);
|
||||
});
|
||||
|
||||
final ProcessorDTO processor;
|
||||
if (properties.isClustered()) {
|
||||
// create the request URL
|
||||
|
@ -385,8 +428,15 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
}
|
||||
processor = entity.getComponent();
|
||||
} else {
|
||||
final ProcessorEntity entity = serviceFacade.setProcessorAnnotationData(revision, id, annotationData);
|
||||
processor = entity.getComponent();
|
||||
// claim the revision
|
||||
serviceFacade.claimRevision(revision, user);
|
||||
try {
|
||||
final ProcessorEntity entity = serviceFacade.setProcessorAnnotationData(revision, id, annotationData);
|
||||
processor = entity.getComponent();
|
||||
} finally {
|
||||
// ensure the revision is canceled.. if the operation succeed, this is a noop
|
||||
serviceFacade.cancelRevision(revision);
|
||||
}
|
||||
}
|
||||
|
||||
// return the processor info
|
||||
|
@ -416,6 +466,12 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
final String id = requestContext.getId();
|
||||
final ControllerServiceDTO controllerService;
|
||||
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getControllerService(id);
|
||||
authorizable.authorize(authorizer, RequestAction.READ);
|
||||
});
|
||||
|
||||
// if the lookup has the service that means we are either a node or
|
||||
// the ncm and the service is available there only
|
||||
if (controllerServiceLookup.getControllerService(id) != null) {
|
||||
|
@ -464,17 +520,32 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
|
||||
@Override
|
||||
public ComponentDetails setAnnotationData(final NiFiWebConfigurationRequestContext requestContext, final String annotationData) {
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
final Revision revision = requestContext.getRevision();
|
||||
final String id = requestContext.getId();
|
||||
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getControllerService(id);
|
||||
authorizable.authorize(authorizer, RequestAction.WRITE);
|
||||
});
|
||||
|
||||
final ControllerServiceDTO controllerService;
|
||||
if (controllerServiceLookup.getControllerService(id) != null) {
|
||||
final ControllerServiceDTO controllerServiceDto = new ControllerServiceDTO();
|
||||
controllerServiceDto.setId(id);
|
||||
controllerServiceDto.setAnnotationData(annotationData);
|
||||
|
||||
final UpdateResult<ControllerServiceEntity> updateResult = serviceFacade.updateControllerService(revision, controllerServiceDto);
|
||||
controllerService = updateResult.getResult().getComponent();
|
||||
// claim the revision
|
||||
serviceFacade.claimRevision(revision, user);
|
||||
try {
|
||||
// perform the update
|
||||
final UpdateResult<ControllerServiceEntity> updateResult = serviceFacade.updateControllerService(revision, controllerServiceDto);
|
||||
controllerService = updateResult.getResult().getComponent();
|
||||
} finally {
|
||||
// ensure the revision is canceled.. if the operation succeed, this is a noop
|
||||
serviceFacade.cancelRevision(revision);
|
||||
}
|
||||
} else {
|
||||
// if this is a standalone instance the service should have been found above... there should
|
||||
// no cluster to replicate the request to
|
||||
|
@ -561,6 +632,12 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
final String id = requestContext.getId();
|
||||
final ReportingTaskDTO reportingTask;
|
||||
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getReportingTask(id);
|
||||
authorizable.authorize(authorizer, RequestAction.READ);
|
||||
});
|
||||
|
||||
// if the provider has the service that means we are either a node or
|
||||
// the ncm and the service is available there only
|
||||
if (reportingTaskProvider.getReportingTaskNode(id) != null) {
|
||||
|
@ -609,17 +686,31 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
|
||||
@Override
|
||||
public ComponentDetails setAnnotationData(final NiFiWebConfigurationRequestContext requestContext, final String annotationData) {
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
final Revision revision = requestContext.getRevision();
|
||||
final String id = requestContext.getId();
|
||||
|
||||
// authorize access
|
||||
serviceFacade.authorizeAccess(lookup -> {
|
||||
final Authorizable authorizable = lookup.getReportingTask(id);
|
||||
authorizable.authorize(authorizer, RequestAction.WRITE);
|
||||
});
|
||||
|
||||
final ReportingTaskDTO reportingTask;
|
||||
if (reportingTaskProvider.getReportingTaskNode(id) != null) {
|
||||
final ReportingTaskDTO reportingTaskDto = new ReportingTaskDTO();
|
||||
reportingTaskDto.setId(id);
|
||||
reportingTaskDto.setAnnotationData(annotationData);
|
||||
|
||||
final UpdateResult<ReportingTaskEntity> updateResult = serviceFacade.updateReportingTask(revision, reportingTaskDto);
|
||||
reportingTask = updateResult.getResult().getComponent();
|
||||
// claim the revision
|
||||
serviceFacade.claimRevision(revision, user);
|
||||
try {
|
||||
final UpdateResult<ReportingTaskEntity> updateResult = serviceFacade.updateReportingTask(revision, reportingTaskDto);
|
||||
reportingTask = updateResult.getResult().getComponent();
|
||||
} finally {
|
||||
// ensure the revision is canceled.. if the operation succeed, this is a noop
|
||||
serviceFacade.cancelRevision(revision);
|
||||
}
|
||||
} else {
|
||||
// if this is a standalone instance the task should have been found above... there should
|
||||
// no cluster to replicate the request to
|
||||
|
@ -768,4 +859,7 @@ public class StandardNiFiWebConfigurationContext implements NiFiWebConfiguration
|
|||
this.reportingTaskProvider = reportingTaskProvider;
|
||||
}
|
||||
|
||||
public void setAuthorizer(Authorizer authorizer) {
|
||||
this.authorizer = authorizer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,331 +0,0 @@
|
|||
/*
|
||||
* 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.nifi.web;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.action.Action;
|
||||
import org.apache.nifi.action.Component;
|
||||
import org.apache.nifi.action.FlowChangeAction;
|
||||
import org.apache.nifi.action.Operation;
|
||||
import org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
|
||||
import org.apache.nifi.action.details.FlowChangeConfigureDetails;
|
||||
import org.apache.nifi.admin.service.AuditService;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserDetails;
|
||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||
import org.apache.nifi.cluster.manager.NodeResponse;
|
||||
import org.apache.nifi.controller.ControllerService;
|
||||
import org.apache.nifi.controller.ControllerServiceLookup;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
|
||||
import org.apache.nifi.web.api.dto.ProcessorDTO;
|
||||
import org.apache.nifi.web.api.dto.RevisionDTO;
|
||||
import org.apache.nifi.web.api.entity.ProcessorEntity;
|
||||
import org.apache.nifi.web.util.ClientResponseUtils;
|
||||
import org.apache.nifi.web.util.WebUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import com.sun.jersey.core.util.MultivaluedMapImpl;
|
||||
|
||||
/**
|
||||
* Implements the NiFiWebContext interface to support a context in both standalone and clustered environments.
|
||||
*/
|
||||
@Deprecated
|
||||
public class StandardNiFiWebContext implements NiFiWebContext {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(StandardNiFiWebContext.class);
|
||||
public static final String CLIENT_ID_PARAM = "clientId";
|
||||
public static final String REVISION_PARAM = "revision";
|
||||
public static final String VERBOSE_PARAM = "verbose";
|
||||
|
||||
private NiFiProperties properties;
|
||||
private NiFiServiceFacade serviceFacade;
|
||||
private ControllerServiceLookup controllerServiceLookup;
|
||||
private AuditService auditService;
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public ControllerService getControllerService(String serviceIdentifier) {
|
||||
return controllerServiceLookup.getControllerService(serviceIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasRole('ROLE_DFM')")
|
||||
public void saveActions(final Collection<ProcessorConfigurationAction> processorActions) {
|
||||
Objects.requireNonNull(processorActions, "Actions cannot be null.");
|
||||
|
||||
// - when running standalone or cluster ncm - actions from custom UIs are stored locally
|
||||
// - clustered nodes do not serve custom UIs directly to users so they should never be invoking this method
|
||||
final Date now = new Date();
|
||||
final Collection<Action> actions = new HashSet<>(processorActions.size());
|
||||
for (final ProcessorConfigurationAction processorAction : processorActions) {
|
||||
final FlowChangeExtensionDetails processorDetails = new FlowChangeExtensionDetails();
|
||||
processorDetails.setType(processorAction.getProcessorType());
|
||||
|
||||
final FlowChangeConfigureDetails configureDetails = new FlowChangeConfigureDetails();
|
||||
configureDetails.setName(processorAction.getName());
|
||||
configureDetails.setPreviousValue(processorAction.getPreviousValue());
|
||||
configureDetails.setValue(processorAction.getValue());
|
||||
|
||||
final FlowChangeAction action = new FlowChangeAction();
|
||||
action.setTimestamp(now);
|
||||
action.setSourceId(processorAction.getProcessorId());
|
||||
action.setSourceName(processorAction.getProcessorName());
|
||||
action.setSourceType(Component.Processor);
|
||||
action.setOperation(Operation.Configure);
|
||||
action.setUserIdentity(getCurrentUserDn());
|
||||
action.setUserName(getCurrentUserName());
|
||||
action.setComponentDetails(processorDetails);
|
||||
action.setActionDetails(configureDetails);
|
||||
actions.add(action);
|
||||
}
|
||||
|
||||
try {
|
||||
// record the operations
|
||||
auditService.addActions(actions);
|
||||
} catch (Throwable t) {
|
||||
logger.warn("Unable to record actions: " + t.getMessage());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(StringUtils.EMPTY, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public String getCurrentUserDn() {
|
||||
String userIdentity = NiFiUser.ANONYMOUS.getIdentity();
|
||||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
if (user != null) {
|
||||
userIdentity = user.getIdentity();
|
||||
}
|
||||
|
||||
return userIdentity;
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public String getCurrentUserName() {
|
||||
String userName = NiFiUser.ANONYMOUS.getIdentity();
|
||||
|
||||
final NiFiUser user = NiFiUserUtils.getNiFiUser();
|
||||
if (user != null) {
|
||||
userName = user.getUserName();
|
||||
}
|
||||
|
||||
return userName;
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_MONITOR', 'ROLE_DFM', 'ROLE_ADMIN')")
|
||||
public ProcessorInfo getProcessor(final NiFiWebContextConfig config) throws ResourceNotFoundException, ClusterRequestException {
|
||||
|
||||
final Revision revision = config.getRevision();
|
||||
final String processorId = config.getProcessorId();
|
||||
|
||||
if (StringUtils.isBlank(processorId)) {
|
||||
throw new ResourceNotFoundException(String.format("Context config did not have a processor ID."));
|
||||
}
|
||||
|
||||
final ProcessorDTO processor;
|
||||
if (properties.isClustered()) {
|
||||
// create the request URL
|
||||
URI requestUrl;
|
||||
try {
|
||||
String path = "/nifi-api/processors/" + URLEncoder.encode(processorId, "UTF-8");
|
||||
requestUrl = new URI(config.getScheme(), null, "localhost", 0, path, null, null);
|
||||
} catch (final URISyntaxException | UnsupportedEncodingException use) {
|
||||
throw new ClusterRequestException(use);
|
||||
}
|
||||
|
||||
// set the request parameters
|
||||
MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
|
||||
parameters.add(CLIENT_ID_PARAM, revision.getClientId());
|
||||
parameters.add(VERBOSE_PARAM, "true");
|
||||
|
||||
// replicate request
|
||||
NodeResponse nodeResponse = null;
|
||||
|
||||
// check for issues replicating request
|
||||
if (nodeResponse.hasThrowable()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new ClusterRequestException(nodeResponse.getThrowable());
|
||||
} else if (nodeResponse.getClientResponse().getStatus() == Response.Status.CONFLICT.getStatusCode()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new InvalidRevisionException(String.format("Invalid revision specified %s", revision));
|
||||
} else if (nodeResponse.getClientResponse().getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new ResourceNotFoundException("Unable to find processor with id: " + processorId);
|
||||
} else if (nodeResponse.getClientResponse().getStatus() != Response.Status.OK.getStatusCode()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new ClusterRequestException("Method resulted in an unsuccessful HTTP response code: " + nodeResponse.getClientResponse().getStatus());
|
||||
}
|
||||
|
||||
// return processor
|
||||
ProcessorEntity entity = (ProcessorEntity) nodeResponse.getUpdatedEntity();
|
||||
if (entity == null) {
|
||||
entity = nodeResponse.getClientResponse().getEntity(ProcessorEntity.class);
|
||||
}
|
||||
processor = entity.getComponent();
|
||||
} else {
|
||||
processor = serviceFacade.getProcessor(processorId).getComponent();
|
||||
}
|
||||
|
||||
// return the processor info
|
||||
final ProcessorConfigDTO processorConfig = processor.getConfig();
|
||||
return new ProcessorInfo.Builder()
|
||||
.id(processor.getId())
|
||||
.name(processor.getName())
|
||||
.state(processor.getState())
|
||||
.annotationData(processorConfig.getAnnotationData())
|
||||
.properties(processorConfig.getProperties())
|
||||
.validateErrors(processor.getValidationErrors()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')")
|
||||
public void setProcessorAnnotationData(final NiFiWebContextConfig config, String annotationData)
|
||||
throws ResourceNotFoundException, InvalidRevisionException, ClusterRequestException {
|
||||
|
||||
final Revision revision = config.getRevision();
|
||||
final String processorId = config.getProcessorId();
|
||||
|
||||
if (StringUtils.isBlank(processorId)) {
|
||||
throw new ResourceNotFoundException(String.format("Context config did not have a processor ID."));
|
||||
}
|
||||
|
||||
if (properties.isClustered()) {
|
||||
|
||||
// create the request URL
|
||||
URI requestUrl;
|
||||
try {
|
||||
String path = "/nifi-api/processors/" + URLEncoder.encode(processorId, "UTF-8");
|
||||
requestUrl = new URI(config.getScheme(), null, "localhost", 0, path, null, null);
|
||||
} catch (final URISyntaxException | UnsupportedEncodingException use) {
|
||||
throw new ClusterRequestException(use);
|
||||
}
|
||||
|
||||
// create the revision
|
||||
RevisionDTO revisionDto = new RevisionDTO();
|
||||
revisionDto.setClientId(revision.getClientId());
|
||||
revisionDto.setVersion(revision.getVersion());
|
||||
|
||||
// create the processor entity
|
||||
ProcessorEntity processorEntity = new ProcessorEntity();
|
||||
processorEntity.setRevision(revisionDto);
|
||||
|
||||
// create the processor dto
|
||||
ProcessorDTO processorDto = new ProcessorDTO();
|
||||
processorEntity.setComponent(processorDto);
|
||||
processorDto.setId(processorId);
|
||||
|
||||
// create the processor configuration with the given annotation data
|
||||
ProcessorConfigDTO configDto = new ProcessorConfigDTO();
|
||||
processorDto.setConfig(configDto);
|
||||
configDto.setAnnotationData(annotationData);
|
||||
|
||||
// set the content type to json
|
||||
final Map<String, String> headers = getHeaders(config);
|
||||
headers.put("Content-Type", "application/json");
|
||||
|
||||
// replicate request
|
||||
NodeResponse nodeResponse = null;
|
||||
|
||||
// check for issues replicating request
|
||||
if (nodeResponse.hasThrowable()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new ClusterRequestException(nodeResponse.getThrowable());
|
||||
} else if (nodeResponse.getClientResponse().getStatus() == Response.Status.CONFLICT.getStatusCode()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new InvalidRevisionException(String.format("Invalid revision specified %s", revision));
|
||||
} else if (nodeResponse.getClientResponse().getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new ResourceNotFoundException("Unable to find processor with id: " + processorId);
|
||||
} else if (nodeResponse.getClientResponse().getStatus() != Response.Status.OK.getStatusCode()) {
|
||||
ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
|
||||
throw new ClusterRequestException("Method resulted in an unsuccessful HTTP response code: " + nodeResponse.getClientResponse().getStatus());
|
||||
}
|
||||
} else {
|
||||
serviceFacade.setProcessorAnnotationData(revision, processorId, annotationData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the headers for the request to replicate to each node while clustered.
|
||||
*
|
||||
* @param config config
|
||||
* @return headers
|
||||
*/
|
||||
private Map<String, String> getHeaders(final NiFiWebContextConfig config) {
|
||||
final Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Accept", "application/json,application/xml");
|
||||
if (StringUtils.isNotBlank(config.getProxiedEntitiesChain())) {
|
||||
headers.put("X-ProxiedEntitiesChain", config.getProxiedEntitiesChain());
|
||||
}
|
||||
|
||||
// add the user's authorities (if any) to the headers
|
||||
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null) {
|
||||
final Object userDetailsObj = authentication.getPrincipal();
|
||||
if (userDetailsObj instanceof NiFiUserDetails) {
|
||||
// serialize user details object
|
||||
final String hexEncodedUserDetails = WebUtils.serializeObjectToHex((Serializable) userDetailsObj);
|
||||
|
||||
// put serialized user details in header
|
||||
headers.put("X-ProxiedEntityUserDetails", hexEncodedUserDetails);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
||||
public void setProperties(NiFiProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public void setServiceFacade(NiFiServiceFacade serviceFacade) {
|
||||
this.serviceFacade = serviceFacade;
|
||||
}
|
||||
|
||||
public void setAuditService(AuditService auditService) {
|
||||
this.auditService = auditService;
|
||||
}
|
||||
|
||||
public void setControllerServiceLookup(ControllerServiceLookup controllerServiceLookup) {
|
||||
this.controllerServiceLookup = controllerServiceLookup;
|
||||
}
|
||||
|
||||
}
|
|
@ -332,12 +332,12 @@ public class ControllerServiceResource extends ApplicationResource {
|
|||
/**
|
||||
* Clears the state for a controller service.
|
||||
*
|
||||
* @param revisionEntity The revision is used to verify the client is working with the latest version of the flow.
|
||||
* @param httpServletRequest servlet request
|
||||
* @param id The id of the controller service
|
||||
* @return a componentStateEntity
|
||||
*/
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{id}/state/clear-requests")
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')")
|
||||
|
@ -359,10 +359,6 @@ public class ControllerServiceResource extends ApplicationResource {
|
|||
)
|
||||
public Response clearState(
|
||||
@Context HttpServletRequest httpServletRequest,
|
||||
@ApiParam(
|
||||
value = "The revision used to verify the client is working with the latest version of the flow.",
|
||||
required = true
|
||||
) final ComponentStateEntity revisionEntity,
|
||||
@ApiParam(
|
||||
value = "The controller service id.",
|
||||
required = true
|
||||
|
|
|
@ -340,15 +340,14 @@ public class ProcessorResource extends ApplicationResource {
|
|||
* Clears the state for a processor.
|
||||
*
|
||||
* @param httpServletRequest servlet request
|
||||
* @param revisionEntity The revision is used to verify the client is working with the latest version of the flow.
|
||||
* @param id The id of the processor
|
||||
* @return a componentStateEntity
|
||||
* @throws InterruptedException if interrupted
|
||||
*/
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/{id}/state/clear-requests")
|
||||
@Path("{id}/state/clear-requests")
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')")
|
||||
@ApiOperation(
|
||||
value = "Clears the state for a processor",
|
||||
|
@ -368,23 +367,14 @@ public class ProcessorResource extends ApplicationResource {
|
|||
)
|
||||
public Response clearState(
|
||||
@Context final HttpServletRequest httpServletRequest,
|
||||
@ApiParam(
|
||||
value = "The revision used to verify the client is working with the latest version of the flow.",
|
||||
required = true
|
||||
) final ComponentStateEntity revisionEntity,
|
||||
@ApiParam(
|
||||
value = "The processor id.",
|
||||
required = true
|
||||
)
|
||||
@PathParam("id") final String id) throws InterruptedException {
|
||||
|
||||
// ensure the revision was specified
|
||||
if (revisionEntity == null) {
|
||||
throw new IllegalArgumentException("Revision must be specified.");
|
||||
}
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.POST, revisionEntity);
|
||||
return replicate(HttpMethod.POST);
|
||||
}
|
||||
|
||||
// handle expects request (usually from the cluster manager)
|
||||
|
|
|
@ -16,27 +16,12 @@
|
|||
*/
|
||||
package org.apache.nifi.web.api;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.wordnik.swagger.annotations.Api;
|
||||
import com.wordnik.swagger.annotations.ApiOperation;
|
||||
import com.wordnik.swagger.annotations.ApiParam;
|
||||
import com.wordnik.swagger.annotations.ApiResponse;
|
||||
import com.wordnik.swagger.annotations.ApiResponses;
|
||||
import com.wordnik.swagger.annotations.Authorization;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.authorization.Authorizer;
|
||||
import org.apache.nifi.authorization.RequestAction;
|
||||
|
@ -56,12 +41,25 @@ import org.apache.nifi.web.api.entity.ReportingTaskEntity;
|
|||
import org.apache.nifi.web.api.request.ClientIdParameter;
|
||||
import org.apache.nifi.web.api.request.LongParameter;
|
||||
|
||||
import com.wordnik.swagger.annotations.Api;
|
||||
import com.wordnik.swagger.annotations.ApiOperation;
|
||||
import com.wordnik.swagger.annotations.ApiParam;
|
||||
import com.wordnik.swagger.annotations.ApiResponse;
|
||||
import com.wordnik.swagger.annotations.ApiResponses;
|
||||
import com.wordnik.swagger.annotations.Authorization;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* RESTful endpoint for managing a Reporting Task.
|
||||
|
@ -320,12 +318,12 @@ public class ReportingTaskResource extends ApplicationResource {
|
|||
/**
|
||||
* Clears the state for a reporting task.
|
||||
*
|
||||
* @param revisionEntity The revision is used to verify the client is working with the latest version of the flow.
|
||||
* @param httpServletRequest servlet request
|
||||
* @param id The id of the reporting task
|
||||
* @return a componentStateEntity
|
||||
*/
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{id}/state/clear-requests")
|
||||
// TODO - @PreAuthorize("hasAnyRole('ROLE_DFM')")
|
||||
|
@ -347,10 +345,6 @@ public class ReportingTaskResource extends ApplicationResource {
|
|||
)
|
||||
public Response clearState(
|
||||
@Context final HttpServletRequest httpServletRequest,
|
||||
@ApiParam(
|
||||
value = "The revision used to verify the client is working with the latest version of the flow.",
|
||||
required = true
|
||||
) final ComponentStateEntity revisionEntity,
|
||||
@ApiParam(
|
||||
value = "The reporting task id.",
|
||||
required = true
|
||||
|
@ -358,7 +352,7 @@ public class ReportingTaskResource extends ApplicationResource {
|
|||
@PathParam("id") final String id) {
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.POST, revisionEntity);
|
||||
return replicate(HttpMethod.POST);
|
||||
}
|
||||
|
||||
// handle expects request (usually from the cluster manager)
|
||||
|
|
|
@ -140,7 +140,6 @@
|
|||
<property name="heartbeatMonitor" ref="heartbeatMonitor" />
|
||||
</bean>
|
||||
|
||||
|
||||
<!-- component ui extension configuration context -->
|
||||
<bean id="nifiWebConfigurationContext" class="org.apache.nifi.web.StandardNiFiWebConfigurationContext">
|
||||
<property name="serviceFacade" ref="serviceFacade"/>
|
||||
|
@ -150,6 +149,7 @@
|
|||
<property name="auditService" ref="auditService"/>
|
||||
<property name="controllerServiceLookup" ref="controllerServiceProvider"/>
|
||||
<property name="reportingTaskProvider" ref="reportingTaskProvider"/>
|
||||
<property name="authorizer" ref="authorizer"/>
|
||||
</bean>
|
||||
|
||||
<!-- rest endpoints -->
|
||||
|
|
|
@ -510,7 +510,7 @@
|
|||
}
|
||||
|
||||
// if this descriptor identifies a controller service, provide a way to create one
|
||||
if (nf.Common.isDefinedAndNotNull(propertyDescriptor.identifiesControllerService) && nf.Common.isDefinedAndNotNull(configurationOptions.groupId)) {
|
||||
if (nf.Common.isDefinedAndNotNull(propertyDescriptor.identifiesControllerService)) {
|
||||
options.push({
|
||||
text: 'Create new service...',
|
||||
value: undefined,
|
||||
|
@ -887,15 +887,21 @@
|
|||
|
||||
// build the controller service entity
|
||||
var controllerServiceEntity = {
|
||||
'controllerService': {
|
||||
'component': {
|
||||
'type': newControllerServiceType
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// determine the appropriate uri for creating the controller service
|
||||
var uri = '../nifi-api/controller/controller-services';
|
||||
if (nf.Common.isDefinedAndNotNull(configurationOptions.groupId)) {
|
||||
uri = '../nifi-api/process-groups/' + encodeURIComponent(configurationOptions.groupId) + '/controller-services';
|
||||
}
|
||||
|
||||
// add the new controller service
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '../nifi-api/process-groups/' + encodeURIComponent(configurationOptions.groupId) + '/controller-services/node',
|
||||
url: uri,
|
||||
data: JSON.stringify(controllerServiceEntity),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
|
@ -913,7 +919,7 @@
|
|||
// add a row for the new property
|
||||
var data = grid.getData();
|
||||
data.updateItem(item.id, $.extend(item, {
|
||||
value: response.controllerService.id
|
||||
value: response.component.id
|
||||
}));
|
||||
|
||||
// close the dialog
|
||||
|
|
|
@ -1348,10 +1348,10 @@ nf.ControllerService = (function () {
|
|||
* @param {type} propertyName
|
||||
*/
|
||||
var getControllerServicePropertyDescriptor = function (propertyName) {
|
||||
var details = $('#controller-service-configuration').data('controllerServiceDetails');
|
||||
var controllerServiceEntity = $('#controller-service-configuration').data('controllerServiceDetails');
|
||||
return $.ajax({
|
||||
type: 'GET',
|
||||
url: details.uri + '/descriptors',
|
||||
url: controllerServiceEntity.component.uri + '/descriptors',
|
||||
data: {
|
||||
propertyName: propertyName
|
||||
},
|
||||
|
@ -1633,7 +1633,7 @@ nf.ControllerService = (function () {
|
|||
// initialize the property table
|
||||
$('#controller-service-properties').propertytable('destroy').propertytable({
|
||||
readOnly: false,
|
||||
groupId: nf.Canvas.getGroupId(),
|
||||
// groupId: controllerServiceEntity.component.parentGroupId,
|
||||
dialogContainer: '#new-controller-service-property-container',
|
||||
descriptorDeferred: getControllerServicePropertyDescriptor,
|
||||
goToServiceDeferred: function () {
|
||||
|
@ -1722,7 +1722,7 @@ nf.ControllerService = (function () {
|
|||
$('#shell-close-button').click();
|
||||
|
||||
// show the custom ui
|
||||
nf.CustomUi.showCustomUi($('#controller-service-id').text(), controllerService.customUiUrl, true).done(function () {
|
||||
nf.CustomUi.showCustomUi(controllerServiceEntity, controllerService.customUiUrl, true).done(function () {
|
||||
// once the custom ui is closed, reload the controller service
|
||||
reloadControllerServiceAndReferencingComponents(serviceTable, controllerService);
|
||||
|
||||
|
@ -1854,7 +1854,7 @@ nf.ControllerService = (function () {
|
|||
$('#shell-close-button').click();
|
||||
|
||||
// show the custom ui
|
||||
nf.CustomUi.showCustomUi(controllerService.id, controllerService.customUiUrl, false).done(function () {
|
||||
nf.CustomUi.showCustomUi(controllerServiceEntity, controllerService.customUiUrl, false).done(function () {
|
||||
nf.Settings.showSettings();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -21,22 +21,21 @@ nf.CustomUi = {
|
|||
/**
|
||||
* Shows the custom ui.
|
||||
*
|
||||
* @argument {string} id The component id
|
||||
* @argument {string} uri The uri for the custom ui
|
||||
* @argument {object} entity The component id
|
||||
* @arugment {string} uri The custom ui uri
|
||||
* @argument {boolean} editable Whether the custom ui should support editing
|
||||
*/
|
||||
showCustomUi: function (id, uri, editable) {
|
||||
showCustomUi: function (entity, uri, editable) {
|
||||
return $.Deferred(function (deferred) {
|
||||
nf.Common.getAccessToken('../nifi-api/access/ui-extension-token').done(function (uiExtensionToken) {
|
||||
// record the processor id
|
||||
$('#shell-close-button');
|
||||
|
||||
var revision = nf.Client.getRevision();
|
||||
var revision = nf.Client.getRevision(entity);
|
||||
|
||||
// build the customer ui params
|
||||
var customUiParams = {
|
||||
'id': id,
|
||||
'processorId': id, // deprecated
|
||||
'id': entity.id,
|
||||
'revision': revision.version,
|
||||
'clientId': revision.clientId,
|
||||
'editable': editable
|
||||
|
|
|
@ -590,12 +590,13 @@ nf.ProcessorConfiguration = (function () {
|
|||
}
|
||||
|
||||
// once everything is loaded, show the dialog
|
||||
$.when.apply(window, requests).done(function (processorResponse, historyResponse) {
|
||||
// get the updated processor
|
||||
processor = processorResponse[0].component;
|
||||
$.when.apply(window, requests).done(function (processorResult, historyResult) {
|
||||
// get the updated processor'
|
||||
var processorResponse = processorResult[0];
|
||||
processor = processorResponse.component;
|
||||
|
||||
// get the processor history
|
||||
var processorHistory = historyResponse[0].componentHistory;
|
||||
var processorHistory = historyResult[0].componentHistory;
|
||||
|
||||
// record the processor details
|
||||
$('#processor-configuration').data('processorDetails', processor);
|
||||
|
@ -747,7 +748,7 @@ nf.ProcessorConfiguration = (function () {
|
|||
$('#processor-configuration').modal('hide');
|
||||
|
||||
// show the custom ui
|
||||
nf.CustomUi.showCustomUi($('#processor-id').text(), processor.config.customUiUrl, true).done(function () {
|
||||
nf.CustomUi.showCustomUi(processorResponse, processor.config.customUiUrl, true).done(function () {
|
||||
// once the custom ui is closed, reload the processor
|
||||
nf.Processor.reload(processor);
|
||||
|
||||
|
|
|
@ -355,7 +355,6 @@ nf.ReportingTask = (function () {
|
|||
// initialize the property table
|
||||
$('#reporting-task-properties').propertytable({
|
||||
readOnly: false,
|
||||
groupId: nf.Canvas.getGroupId(),
|
||||
dialogContainer: '#new-reporting-task-property-container',
|
||||
descriptorDeferred: getReportingTaskPropertyDescriptor,
|
||||
goToServiceDeferred: goToServiceFromProperty
|
||||
|
@ -377,7 +376,6 @@ nf.ReportingTask = (function () {
|
|||
// initialize the property table
|
||||
$('#reporting-task-properties').propertytable('destroy').propertytable({
|
||||
readOnly: false,
|
||||
groupId: nf.Canvas.getGroupId(),
|
||||
dialogContainer: '#new-reporting-task-property-container',
|
||||
descriptorDeferred: getReportingTaskPropertyDescriptor,
|
||||
goToServiceDeferred: goToServiceFromProperty
|
||||
|
@ -503,7 +501,7 @@ nf.ReportingTask = (function () {
|
|||
$('#shell-close-button').click();
|
||||
|
||||
// show the custom ui
|
||||
nf.CustomUi.showCustomUi($('#reporting-task-id').text(), reportingTask.customUiUrl, true).done(function () {
|
||||
nf.CustomUi.showCustomUi(reportingTaskEntity, reportingTask.customUiUrl, true).done(function () {
|
||||
// once the custom ui is closed, reload the reporting task
|
||||
nf.ReportingTask.reload(reportingTaskEntity.id).done(function (response) {
|
||||
nf.ControllerService.reloadReferencedServices(getControllerServicesTable(), response.reportingTask);
|
||||
|
@ -634,7 +632,7 @@ nf.ReportingTask = (function () {
|
|||
$('#shell-close-button').click();
|
||||
|
||||
// show the custom ui
|
||||
nf.CustomUi.showCustomUi(reportingTask.id, reportingTask.customUiUrl, false).done(function() {
|
||||
nf.CustomUi.showCustomUi(reportingTaskEntity, reportingTask.customUiUrl, false).done(function() {
|
||||
nf.Settings.showSettings();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -209,10 +209,10 @@ nf.ProcessorDetails = (function () {
|
|||
});
|
||||
|
||||
// show the dialog once we have the processor and its history
|
||||
$.when(getProcessor, getProcessorHistory).done(function (processorResponse, historyResponse) {
|
||||
var processorResponse = processorResponse[0];
|
||||
$.when(getProcessor, getProcessorHistory).done(function (processorResult, historyResult) {
|
||||
var processorResponse = processorResult[0];
|
||||
var processor = processorResponse.component;
|
||||
var historyResponse = historyResponse[0];
|
||||
var historyResponse = historyResult[0];
|
||||
var history = historyResponse.componentHistory;
|
||||
|
||||
// load the properties
|
||||
|
@ -238,7 +238,7 @@ nf.ProcessorDetails = (function () {
|
|||
$('#processor-details').modal('hide');
|
||||
|
||||
// show the custom ui
|
||||
nf.CustomUi.showCustomUi(processor.id, processor.config.customUiUrl, false);
|
||||
nf.CustomUi.showCustomUi(processorResponse, processor.config.customUiUrl, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue