diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java index cc0d8fc3ff..39e96422dc 100644 --- a/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java +++ b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/Authorizable.java @@ -41,7 +41,7 @@ public interface Authorizable { /** * The Resource for this Authorizable. * - * @return the parent resource + * @return the resource */ Resource getResource(); diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/ComponentAuthorizable.java b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/ComponentAuthorizable.java new file mode 100644 index 0000000000..7fd3d5a775 --- /dev/null +++ b/nifi-framework-api/src/main/java/org/apache/nifi/authorization/resource/ComponentAuthorizable.java @@ -0,0 +1,39 @@ +/* + * 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.authorization.resource; + +/** + * Not all Authorizables are components, however all ComponentAuthorizable's are components. This ensures that they + * will have an identifier and a ProcessGroup identifier. + */ +public interface ComponentAuthorizable extends Authorizable { + + /** + * The identifier of the underlying component. + * + * @return the identifier + */ + String getIdentifier(); + + /** + * The identifier of the ProcessGroup this component belongs to. + * + * @return the ProcessGroup identifier + */ + String getProcessGroupIdentifier(); + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicySummaryDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicySummaryDTO.java index 0fb97c1a4a..e5a6903571 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicySummaryDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/AccessPolicySummaryDTO.java @@ -17,6 +17,7 @@ package org.apache.nifi.web.api.dto; import com.wordnik.swagger.annotations.ApiModelProperty; +import org.apache.nifi.web.api.entity.ComponentReferenceEntity; import javax.xml.bind.annotation.XmlType; @@ -28,6 +29,7 @@ public class AccessPolicySummaryDTO extends ComponentDTO { private String resource; private String action; + private ComponentReferenceEntity componentReference; /** * @return The action associated with this access policy. @@ -56,4 +58,15 @@ public class AccessPolicySummaryDTO extends ComponentDTO { this.resource = resource; } + /** + * @return Component this policy references if applicable. + */ + @ApiModelProperty(value="Component this policy references if applicable.") + public ComponentReferenceEntity getComponentReference() { + return componentReference; + } + + public void setComponentReference(ComponentReferenceEntity componentReference) { + this.componentReference = componentReference; + } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentReferenceDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentReferenceDTO.java new file mode 100644 index 0000000000..48aacaa9eb --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ComponentReferenceDTO.java @@ -0,0 +1,76 @@ +/* + * 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.api.dto; + +import com.wordnik.swagger.annotations.ApiModelProperty; + +import javax.xml.bind.annotation.XmlType; + +/** + * Details for the access configuration. + */ +@XmlType(name = "accessPolicy") +public class ComponentReferenceDTO extends ComponentDTO { + + private String id; + private String parentGroupId; + private String name; + + /** + * The id for this component. + * + * @return The id + */ + @ApiModelProperty( + value = "The id of the component." + ) + public String getId() { + return this.id; + } + + public void setId(final String id) { + this.id = id; + } + + /** + * @return id for the parent group of this component if applicable, null otherwise + */ + @ApiModelProperty( + value = "The id of parent process group of this component if applicable." + ) + public String getParentGroupId() { + return parentGroupId; + } + + public void setParentGroupId(String parentGroupId) { + this.parentGroupId = parentGroupId; + } + + /** + * @return id for the parent group of this component if applicable, null otherwise + */ + @ApiModelProperty( + value = "The name of the component." + ) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/UserGroupDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/UserGroupDTO.java index af63a14e2a..17de4ded7c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/UserGroupDTO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/UserGroupDTO.java @@ -48,7 +48,9 @@ public class UserGroupDTO extends TenantDTO { * @return policies this user group is part of */ @ApiModelProperty( - value = "The access policies this user group belongs to.", + value = "The access policies this user group belongs to. This field was incorrectly defined as an AccessPolicyEntity. For " + + "compatibility reasons the field will remain of this type, however only the fields that are present in the " + + "AccessPolicySummaryEntity will be populated here.", readOnly = true ) public Set getAccessPolicies() { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ComponentReferenceEntity.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ComponentReferenceEntity.java new file mode 100644 index 0000000000..bc03ad8a5b --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/entity/ComponentReferenceEntity.java @@ -0,0 +1,61 @@ +/* + * 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.api.entity; + +import com.wordnik.swagger.annotations.ApiModelProperty; +import org.apache.nifi.web.api.dto.ComponentReferenceDTO; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * A serialized representation of this class can be placed in the entity body of a request or response to or from the API. + * This particular entity holds a reference to an {@link ComponentReferenceDTO}. + */ +@XmlRootElement(name = "componentReferenceEntity") +public class ComponentReferenceEntity extends ComponentEntity { + + private String parentGroupId; + private ComponentReferenceDTO component; + + /** + * @return id for the parent group of this component if applicable, null otherwise + */ + @ApiModelProperty( + value = "The id of parent process group of this component if applicable." + ) + public String getParentGroupId() { + return parentGroupId; + } + + public void setParentGroupId(String parentGroupId) { + this.parentGroupId = parentGroupId; + } + + /** + * The {@link ComponentReferenceDTO} that is being serialized. + * + * @return The {@link ComponentReferenceDTO} object + */ + public ComponentReferenceDTO getComponent() { + return component; + } + + public void setComponent(ComponentReferenceDTO component) { + this.component = component; + } + +} diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java index 99e06ed053..94e07452fc 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/connectable/Connectable.java @@ -16,12 +16,7 @@ */ package org.apache.nifi.connectable; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ComponentAuthorizable; import org.apache.nifi.components.ValidationResult; import org.apache.nifi.controller.Triggerable; import org.apache.nifi.groups.ProcessGroup; @@ -29,10 +24,15 @@ import org.apache.nifi.processor.ProcessSession; import org.apache.nifi.processor.Relationship; import org.apache.nifi.scheduling.SchedulingStrategy; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + /** * Represents a connectable component to which or from which data can flow. */ -public interface Connectable extends Triggerable, Authorizable, Positionable { +public interface Connectable extends Triggerable, ComponentAuthorizable, Positionable { /** * @return the unique identifier for this Connectable diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractConfiguredComponent.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractConfiguredComponent.java index cc9404eea3..671f4fb6c7 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractConfiguredComponent.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractConfiguredComponent.java @@ -371,8 +371,6 @@ public abstract class AbstractConfiguredComponent implements ConfigurableCompone public abstract void verifyModifiable() throws IllegalStateException; - protected abstract String getProcessGroupIdentifier(); - /** * */ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java index 581d209982..ff42f47748 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/AbstractPort.java @@ -16,22 +16,6 @@ */ package org.apache.nifi.controller; -import static java.util.Objects.requireNonNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.nifi.authorization.Resource; @@ -52,6 +36,22 @@ import org.apache.nifi.processor.Relationship; import org.apache.nifi.processor.exception.ProcessException; import org.apache.nifi.util.FormatUtils; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import static java.util.Objects.requireNonNull; + public abstract class AbstractPort implements Port { public static final Relationship PORT_RELATIONSHIP = new Relationship.Builder() @@ -120,6 +120,12 @@ public abstract class AbstractPort implements Port { return id; } + @Override + public String getProcessGroupIdentifier() { + final ProcessGroup procGroup = getProcessGroup(); + return procGroup == null ? null : procGroup.getIdentifier(); + } + @Override public String getName() { return name.get(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java index 91119ec0ff..7ec3a14e0e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ConfiguredComponent.java @@ -16,14 +16,14 @@ */ package org.apache.nifi.controller; -import java.util.Collection; -import java.util.Map; - -import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ComponentAuthorizable; import org.apache.nifi.components.PropertyDescriptor; import org.apache.nifi.components.ValidationResult; -public interface ConfiguredComponent extends Authorizable { +import java.util.Collection; +import java.util.Map; + +public interface ConfiguredComponent extends ComponentAuthorizable { public String getIdentifier(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java index c4cdf345f8..18bcc3cb4d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/StandardFunnel.java @@ -109,6 +109,12 @@ public class StandardFunnel implements Funnel { return identifier; } + @Override + public String getProcessGroupIdentifier() { + final ProcessGroup procGroup = getProcessGroup(); + return procGroup == null ? null : procGroup.getIdentifier(); + } + @Override public Collection getRelationships() { return relationships; diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java index 7274458e2b..f0771bedc1 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/Template.java @@ -18,12 +18,13 @@ package org.apache.nifi.controller; import org.apache.nifi.authorization.Resource; import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ComponentAuthorizable; import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.resource.ResourceType; import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.web.api.dto.TemplateDTO; -public class Template implements Authorizable { +public class Template implements ComponentAuthorizable { private final TemplateDTO dto; private volatile ProcessGroup processGroup; @@ -32,10 +33,17 @@ public class Template implements Authorizable { this.dto = dto; } + @Override public String getIdentifier() { return dto.getId(); } + @Override + public String getProcessGroupIdentifier() { + final ProcessGroup procGroup = getProcessGroup(); + return procGroup == null ? null : procGroup.getIdentifier(); + } + /** * Returns a TemplateDTO object that describes the contents of this Template * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java index 352f73f188..bc1be00fee 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/label/Label.java @@ -16,14 +16,14 @@ */ package org.apache.nifi.controller.label; -import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ComponentAuthorizable; import org.apache.nifi.connectable.Positionable; import org.apache.nifi.connectable.Size; import org.apache.nifi.groups.ProcessGroup; import java.util.Map; -public interface Label extends Authorizable, Positionable { +public interface Label extends ComponentAuthorizable, Positionable { String getIdentifier(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java index fd4673d28c..be0bcd3876 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/ProcessGroup.java @@ -16,7 +16,7 @@ */ package org.apache.nifi.groups; -import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ComponentAuthorizable; import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.Connection; import org.apache.nifi.connectable.Funnel; @@ -45,7 +45,7 @@ import java.util.function.Predicate; *

* MUST BE THREAD-SAFE

*/ -public interface ProcessGroup extends Authorizable, Positionable { +public interface ProcessGroup extends ComponentAuthorizable, Positionable { /** * Predicate for filtering schedulable Processors. diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java index ff96fba025..133f274e23 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/groups/RemoteProcessGroup.java @@ -16,7 +16,7 @@ */ package org.apache.nifi.groups; -import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ComponentAuthorizable; import org.apache.nifi.connectable.Positionable; import org.apache.nifi.controller.exception.CommunicationsException; import org.apache.nifi.events.EventReporter; @@ -28,7 +28,7 @@ import java.util.Date; import java.util.Set; import java.util.concurrent.TimeUnit; -public interface RemoteProcessGroup extends Authorizable, Positionable { +public interface RemoteProcessGroup extends ComponentAuthorizable, Positionable { String getIdentifier(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java index aede8256f6..bfa2129b7e 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/StandardProcessorNode.java @@ -1443,7 +1443,7 @@ public class StandardProcessorNode extends ProcessorNode implements Connectable } @Override - protected String getProcessGroupIdentifier() { + public String getProcessGroupIdentifier() { final ProcessGroup group = getProcessGroup(); return group == null ? null : group.getIdentifier(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java index a95cb45316..704479672d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/label/StandardLabel.java @@ -79,6 +79,12 @@ public class StandardLabel implements Label { return identifier; } + @Override + public String getProcessGroupIdentifier() { + final ProcessGroup procGroup = getProcessGroup(); + return procGroup == null ? null : procGroup.getIdentifier(); + } + @Override public Authorizable getParentAuthorizable() { return getProcessGroup(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java index dc8056d1b7..ac5525c923 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/reporting/AbstractReportingTaskNode.java @@ -16,12 +16,6 @@ */ package org.apache.nifi.controller.reporting; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - import org.apache.nifi.components.ValidationResult; import org.apache.nifi.controller.AbstractConfiguredComponent; import org.apache.nifi.controller.ConfigurationContext; @@ -39,6 +33,12 @@ import org.apache.nifi.reporting.ReportingTask; import org.apache.nifi.scheduling.SchedulingStrategy; import org.apache.nifi.util.FormatUtils; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + public abstract class AbstractReportingTaskNode extends AbstractConfiguredComponent implements ReportingTaskNode { private final ReportingTask reportingTask; @@ -238,7 +238,7 @@ public abstract class AbstractReportingTaskNode extends AbstractConfiguredCompon } @Override - protected String getProcessGroupIdentifier() { + public String getProcessGroupIdentifier() { return null; } } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java index e5a3b83e9b..c61325ac1b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/StandardControllerServiceNode.java @@ -428,7 +428,7 @@ public class StandardControllerServiceNode extends AbstractConfiguredComponent i } @Override - protected String getProcessGroupIdentifier() { + public String getProcessGroupIdentifier() { final ProcessGroup procGroup = getProcessGroup(); return procGroup == null ? null : procGroup.getIdentifier(); } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java index fcfe8389fe..312103e28d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java @@ -161,6 +161,16 @@ public final class StandardProcessGroup implements ProcessGroup { return id; } + @Override + public String getProcessGroupIdentifier() { + final ProcessGroup parentProcessGroup = getParent(); + if (parentProcessGroup == null) { + return null; + } else { + return parentProcessGroup.getIdentifier(); + } + } + @Override public String getName() { return name.get(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java index 78968e2a28..091f00e2b4 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/remote/StandardRemoteProcessGroup.java @@ -205,6 +205,12 @@ public class StandardRemoteProcessGroup implements RemoteProcessGroup { return id; } + @Override + public String getProcessGroupIdentifier() { + final ProcessGroup procGroup = getProcessGroup(); + return procGroup == null ? null : procGroup.getIdentifier(); + } + @Override public Authorizable getParentAuthorizable() { return getProcessGroup(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java index 27c629cefd..47faca5b0c 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/mock/MockProcessGroup.java @@ -60,6 +60,11 @@ public class MockProcessGroup implements ProcessGroup { return null; } + @Override + public String getProcessGroupIdentifier() { + return null; + } + @Override public void setParent(final ProcessGroup group) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java index 18c029b1f7..53c0fe6471 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java @@ -37,6 +37,7 @@ import org.apache.nifi.authorization.Resource; import org.apache.nifi.authorization.User; import org.apache.nifi.authorization.UserContextKeys; import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.EnforcePolicyPermissionsThroughBaseResource; import org.apache.nifi.authorization.resource.ResourceFactory; import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.NiFiUserUtils; @@ -95,6 +96,7 @@ import org.apache.nifi.web.api.dto.BulletinQueryDTO; import org.apache.nifi.web.api.dto.ClusterDTO; import org.apache.nifi.web.api.dto.ComponentDTO; import org.apache.nifi.web.api.dto.ComponentHistoryDTO; +import org.apache.nifi.web.api.dto.ComponentReferenceDTO; import org.apache.nifi.web.api.dto.ComponentStateDTO; import org.apache.nifi.web.api.dto.ConnectionDTO; import org.apache.nifi.web.api.dto.ControllerConfigurationDTO; @@ -154,6 +156,7 @@ import org.apache.nifi.web.api.entity.AccessPolicyEntity; import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity; import org.apache.nifi.web.api.entity.ActionEntity; import org.apache.nifi.web.api.entity.BulletinEntity; +import org.apache.nifi.web.api.entity.ComponentReferenceEntity; import org.apache.nifi.web.api.entity.ConnectionEntity; import org.apache.nifi.web.api.entity.ConnectionStatusEntity; import org.apache.nifi.web.api.entity.ControllerBulletinsEntity; @@ -485,7 +488,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { accessPolicy -> { final Set users = accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); final Set userGroups = accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()); - return dtoFactory.createAccessPolicyDto(accessPolicy, userGroups, users); + final ComponentReferenceEntity componentReference = createComponentReferenceEntity(accessPolicy.getResource()); + return dtoFactory.createAccessPolicyDto(accessPolicy, userGroups, users, componentReference); }); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizable); @@ -513,10 +517,16 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { @Override public UserGroupEntity updateUserGroup(final Revision revision, final UserGroupDTO userGroupDTO) { final Authorizable userGroupsAuthorizable = authorizableLookup.getTenant(); + final Set policies = userGroupDAO.getAccessPoliciesForUserGroup(userGroupDTO.getId()); final RevisionUpdate snapshot = updateComponent(revision, userGroupsAuthorizable, () -> userGroupDAO.updateUserGroup(userGroupDTO), - userGroup -> dtoFactory.createUserGroupDto(userGroup, userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()))); + userGroup -> { + final Set tenantEntities = userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); + final Set policyEntities = policies.stream().map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); + return dtoFactory.createUserGroupDto(userGroup, tenantEntities, policyEntities); + } + ); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(userGroupsAuthorizable); return entityFactory.createUserGroupEntity(snapshot.getComponent(), dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions); @@ -966,8 +976,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final Group userGroup = userGroupDAO.getUserGroup(userGroupId); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getTenant()); final Set users = userGroup != null ? userGroup.getUsers().stream() - .map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : - null; + .map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null; + final Set policyEntities = userGroupDAO.getAccessPoliciesForUserGroup(userGroup.getIdentifier()).stream() + .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); final String resourceIdentifier = ResourceFactory.getTenantResource().getIdentifier() + "/" + userGroupId; final UserGroupDTO snapshot = deleteComponent( @@ -985,7 +996,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { }, () -> userGroupDAO.deleteUserGroup(userGroupId), false, // no user group specific policies to remove - dtoFactory.createUserGroupDto(userGroup, users)); + dtoFactory.createUserGroupDto(userGroup, users, policyEntities)); return entityFactory.createUserGroupEntity(snapshot, null, permissions); } @@ -993,6 +1004,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { @Override public AccessPolicyEntity deleteAccessPolicy(final Revision revision, final String accessPolicyId) { final AccessPolicy accessPolicy = accessPolicyDAO.getAccessPolicy(accessPolicyId); + final ComponentReferenceEntity componentReference = createComponentReferenceEntity(accessPolicy.getResource()); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getAccessPolicyById(accessPolicyId)); final Set userGroups = accessPolicy != null ? accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()) : null; final Set users = accessPolicy != null ? accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null; @@ -1011,8 +1023,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { }, () -> accessPolicyDAO.deleteAccessPolicy(accessPolicyId), false, // no need to clean up any policies as it's already been removed above - dtoFactory.createAccessPolicyDto(accessPolicy, userGroups, - users)); + dtoFactory.createAccessPolicyDto(accessPolicy, userGroups, users, componentReference)); return entityFactory.createAccessPolicyEntity(snapshot, null, permissions); } @@ -1350,13 +1361,14 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { final String creator = NiFiUserUtils.getNiFiUserIdentity(); final AccessPolicy newAccessPolicy = accessPolicyDAO.createAccessPolicy(accessPolicyDTO); + final ComponentReferenceEntity componentReference = createComponentReferenceEntity(newAccessPolicy.getResource()); final AccessPolicyDTO newAccessPolicyDto = dtoFactory.createAccessPolicyDto(newAccessPolicy, newAccessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()), newAccessPolicy.getUsers().stream().map(userId -> { final RevisionDTO userRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userId)); return entityFactory.createTenantEntity(dtoFactory.createTenantDTO(userDAO.getUser(userId)), userRevision, dtoFactory.createPermissionsDto(tenantAuthorizable)); - }).collect(Collectors.toSet())); + }).collect(Collectors.toSet()), componentReference); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getAccessPolicyById(accessPolicyDTO.getId())); return entityFactory.createAccessPolicyEntity(newAccessPolicyDto, dtoFactory.createRevisionDTO(new FlowModification(revision, creator)), permissions); @@ -1376,8 +1388,34 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { return entityFactory.createUserEntity(newUserDto, dtoFactory.createRevisionDTO(new FlowModification(revision, creator)), permissions); } + private ComponentReferenceEntity createComponentReferenceEntity(final String resource) { + ComponentReferenceEntity componentReferenceEntity = null; + try { + // get the component authorizable + Authorizable componentAuthorizable = authorizableLookup.getAuthorizableFromResource(resource); + + // if this represents an authorizable whose policy permissions are enforced through the base resource, + // get the underlying base authorizable for the component reference + if (componentAuthorizable instanceof EnforcePolicyPermissionsThroughBaseResource) { + componentAuthorizable = ((EnforcePolicyPermissionsThroughBaseResource) componentAuthorizable).getBaseAuthorizable(); + } + + final ComponentReferenceDTO componentReference = dtoFactory.createComponentReferenceDto(componentAuthorizable); + if (componentReference != null) { + final PermissionsDTO componentReferencePermissions = dtoFactory.createPermissionsDto(componentAuthorizable); + final RevisionDTO componentReferenceRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(componentReference.getId())); + componentReferenceEntity = entityFactory.createComponentReferenceEntity(componentReference, componentReferenceRevision, componentReferencePermissions); + } + } catch (final ResourceNotFoundException e) { + // component not found for the specified resource + } + + return componentReferenceEntity; + } + private AccessPolicySummaryEntity createAccessPolicySummaryEntity(final AccessPolicy ap) { - final AccessPolicySummaryDTO apSummary = dtoFactory.createAccessPolicySummaryDto(ap); + final ComponentReferenceEntity componentReference = createComponentReferenceEntity(ap.getResource()); + final AccessPolicySummaryDTO apSummary = dtoFactory.createAccessPolicySummaryDto(ap, componentReference); final PermissionsDTO apPermissions = dtoFactory.createPermissionsDto(authorizableLookup.getAccessPolicyById(ap.getIdentifier())); final RevisionDTO apRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(ap.getIdentifier())); return entityFactory.createAccessPolicySummaryEntity(apSummary, apRevision, apPermissions); @@ -1385,15 +1423,12 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { @Override public UserGroupEntity createUserGroup(final Revision revision, final UserGroupDTO userGroupDTO) { - final Authorizable tenantAuthorizable = authorizableLookup.getTenant(); final String creator = NiFiUserUtils.getNiFiUserIdentity(); final Group newUserGroup = userGroupDAO.createUserGroup(userGroupDTO); - final UserGroupDTO newUserGroupDto = dtoFactory.createUserGroupDto(newUserGroup, newUserGroup.getUsers().stream() - .map(userId -> { - final RevisionDTO userRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userId)); - return entityFactory.createTenantEntity(dtoFactory.createTenantDTO(userDAO.getUser(userId)), userRevision, - dtoFactory.createPermissionsDto(tenantAuthorizable)); - }).collect(Collectors.toSet())); + final Set tenantEntities = newUserGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); + final Set policyEntities = userGroupDAO.getAccessPoliciesForUserGroup(newUserGroup.getIdentifier()).stream() + .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); + final UserGroupDTO newUserGroupDto = dtoFactory.createUserGroupDto(newUserGroup, tenantEntities, policyEntities); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getTenant()); return entityFactory.createUserGroupEntity(newUserGroupDto, dtoFactory.createRevisionDTO(new FlowModification(revision, creator)), permissions); @@ -2657,10 +2692,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { private AccessPolicyEntity createAccessPolicyEntity(final AccessPolicy accessPolicy) { final RevisionDTO revision = dtoFactory.createRevisionDTO(revisionManager.getRevision(accessPolicy.getIdentifier())); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getAccessPolicyById(accessPolicy.getIdentifier())); + final ComponentReferenceEntity componentReference = createComponentReferenceEntity(accessPolicy.getResource()); return entityFactory.createAccessPolicyEntity( dtoFactory.createAccessPolicyDto(accessPolicy, accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()), - accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet())), + accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()), componentReference), revision, permissions); } @@ -2690,9 +2726,11 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade { private UserGroupEntity createUserGroupEntity(final Group userGroup) { final RevisionDTO userGroupRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(userGroup.getIdentifier())); + final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getTenant()); final Set users = userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet()); - return entityFactory.createUserGroupEntity(dtoFactory.createUserGroupDto(userGroup, users), userGroupRevision, - dtoFactory.createPermissionsDto(authorizableLookup.getTenant())); + final Set policyEntities = userGroupDAO.getAccessPoliciesForUserGroup(userGroup.getIdentifier()).stream() + .map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet()); + return entityFactory.createUserGroupEntity(dtoFactory.createUserGroupDto(userGroup, users, policyEntities), userGroupRevision, permissions); } @Override diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java index c39af2fecf..3383632b04 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java @@ -42,6 +42,7 @@ import org.apache.nifi.authorization.RequestAction; import org.apache.nifi.authorization.Resource; import org.apache.nifi.authorization.User; import org.apache.nifi.authorization.resource.Authorizable; +import org.apache.nifi.authorization.resource.ComponentAuthorizable; import org.apache.nifi.authorization.user.NiFiUserUtils; import org.apache.nifi.cluster.coordination.heartbeat.NodeHeartbeat; import org.apache.nifi.cluster.coordination.node.NodeConnectionStatus; @@ -140,9 +141,11 @@ import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO; import org.apache.nifi.web.api.dto.status.ProcessorStatusSnapshotDTO; import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO; import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusSnapshotDTO; +import org.apache.nifi.web.api.entity.AccessPolicyEntity; import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity; import org.apache.nifi.web.api.entity.AllowableValueEntity; import org.apache.nifi.web.api.entity.BulletinEntity; +import org.apache.nifi.web.api.entity.ComponentReferenceEntity; import org.apache.nifi.web.api.entity.ConnectionStatusSnapshotEntity; import org.apache.nifi.web.api.entity.FlowBreadcrumbEntity; import org.apache.nifi.web.api.entity.PortStatusSnapshotEntity; @@ -737,15 +740,32 @@ public final class DtoFactory { * @param userGroup user group * @return dto */ - public UserGroupDTO createUserGroupDto(final Group userGroup, Set users) { + public UserGroupDTO createUserGroupDto(final Group userGroup, Set users, final Set accessPolicies) { if (userGroup == null) { return null; } + // convert to access policies to handle backward compatibility due to incorrect + // type in the UserGroupDTO + final Set policies = accessPolicies.stream().map(summaryEntity -> { + final AccessPolicyDTO policy = new AccessPolicyDTO(); + policy.setId(summaryEntity.getId()); + + if (summaryEntity.getPermissions().getCanRead()) { + final AccessPolicySummaryDTO summary = summaryEntity.getComponent(); + policy.setResource(summary.getResource()); + policy.setAction(summary.getAction()); + policy.setComponentReference(summary.getComponentReference()); + } + + return entityFactory.createAccessPolicyEntity(policy, summaryEntity.getRevision(), summaryEntity.getPermissions()); + }).collect(Collectors.toSet()); + final UserGroupDTO dto = new UserGroupDTO(); dto.setId(userGroup.getIdentifier()); dto.setUsers(users); dto.setIdentity(userGroup.getName()); + dto.setAccessPolicies(policies); return dto; } @@ -1584,7 +1604,20 @@ public final class DtoFactory { return dto; } - public AccessPolicySummaryDTO createAccessPolicySummaryDto(final AccessPolicy accessPolicy) { + public ComponentReferenceDTO createComponentReferenceDto(final Authorizable authorizable) { + if (authorizable == null || !(authorizable instanceof ComponentAuthorizable)) { + return null; + } + + final ComponentAuthorizable componentAuthorizable = (ComponentAuthorizable) authorizable; + final ComponentReferenceDTO dto = new ComponentReferenceDTO(); + dto.setId(componentAuthorizable.getIdentifier()); + dto.setParentGroupId(componentAuthorizable.getProcessGroupIdentifier()); + dto.setName(authorizable.getResource().getName()); + return dto; + } + + public AccessPolicySummaryDTO createAccessPolicySummaryDto(final AccessPolicy accessPolicy, final ComponentReferenceEntity componentReference) { if (accessPolicy == null) { return null; } @@ -1593,10 +1626,13 @@ public final class DtoFactory { dto.setId(accessPolicy.getIdentifier()); dto.setResource(accessPolicy.getResource()); dto.setAction(accessPolicy.getAction().toString()); + dto.setComponentReference(componentReference); return dto; } - public AccessPolicyDTO createAccessPolicyDto(final AccessPolicy accessPolicy, Set userGroups, Set users) { + public AccessPolicyDTO createAccessPolicyDto(final AccessPolicy accessPolicy, final Set userGroups, + final Set users, final ComponentReferenceEntity componentReference) { + if (accessPolicy == null) { return null; } @@ -1607,6 +1643,7 @@ public final class DtoFactory { dto.setId(accessPolicy.getIdentifier()); dto.setResource(accessPolicy.getResource()); dto.setAction(accessPolicy.getAction().toString()); + dto.setComponentReference(componentReference); return dto; } diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java index 2a25447711..41249bafb4 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java @@ -35,6 +35,7 @@ import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity; import org.apache.nifi.web.api.entity.ActionEntity; import org.apache.nifi.web.api.entity.AllowableValueEntity; import org.apache.nifi.web.api.entity.BulletinEntity; +import org.apache.nifi.web.api.entity.ComponentReferenceEntity; import org.apache.nifi.web.api.entity.ConnectionEntity; import org.apache.nifi.web.api.entity.ConnectionStatusEntity; import org.apache.nifi.web.api.entity.ConnectionStatusSnapshotEntity; @@ -294,6 +295,21 @@ public final class EntityFactory { return entity; } + public ComponentReferenceEntity createComponentReferenceEntity(final ComponentReferenceDTO dto, final RevisionDTO revision, final PermissionsDTO permissions) { + final ComponentReferenceEntity entity = new ComponentReferenceEntity(); + entity.setRevision(revision); + if (dto != null) { + entity.setPermissions(permissions); + entity.setId(dto.getId()); + entity.setParentGroupId(dto.getParentGroupId()); + + if (permissions != null && permissions.getCanRead()) { + entity.setComponent(dto); + } + } + return entity; + } + public UserGroupEntity createUserGroupEntity(final UserGroupDTO dto, final RevisionDTO revision, final PermissionsDTO permissions) { final UserGroupEntity entity = new UserGroupEntity(); entity.setRevision(revision); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java index 1dc9a6d03e..9a579ef320 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/UserGroupDAO.java @@ -62,6 +62,14 @@ public interface UserGroupDAO { */ Set getAccessPoliciesForUser(String userId); + /** + * Gets the access policies for the user group with the specified ID. + * + * @param userGroupId The user group ID + * @return The set of access policies + */ + Set getAccessPoliciesForUserGroup(String userGroupId); + /** * Gets all user groups. * diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java index 24bcbef1a8..a47c0517de 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardPolicyBasedAuthorizerDAO.java @@ -277,6 +277,16 @@ public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGr .collect(Collectors.toSet()); } + @Override + public Set getAccessPoliciesForUserGroup(String userGroupId) { + return authorizer.getAccessPolicies().stream() + .filter(p -> { + // policy contains the user group + return p.getGroups().contains(userGroupId); + }) + .collect(Collectors.toSet()); + } + @Override public Set getUserGroups() { return authorizer.getGroups(); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp index 473f538ff2..28ecd52a4b 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/pages/users.jsp @@ -32,6 +32,7 @@ + @@ -64,6 +65,7 @@ + diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/users/user-policies-dialog.jsp b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/users/user-policies-dialog.jsp new file mode 100644 index 0000000000..b38a101ba5 --- /dev/null +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/users/user-policies-dialog.jsp @@ -0,0 +1,29 @@ +<%-- + 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. +--%> +<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %> + \ No newline at end of file diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/users.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/users.css index 1cacd2bca7..f380c89dba 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/users.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/users.css @@ -81,6 +81,38 @@ background-color: #fff; } +/* user policies table */ + +#policies-dialog-user-name { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +#user-policies-table { + position: absolute; + top: 40px; + left: 0px; + bottom: 33px; + right: 0px; + overflow: hidden; + background-color: #fff; +} + +#user-policy-message { + position: absolute; + color: #775351; + font-family: Roboto; + font-size: 13px; + right: 0px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + left: 0px; + bottom: 0px; + height: 13px; +} + /* users dialog */ #user-dialog { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css index 780d0d30ca..ecb4c63989 100755 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/jquery/slickgrid/css/slick-default-theme.css @@ -7,6 +7,7 @@ classes should alter those! .slick-header-columns { color: #fff; + background-color: #728E9B; } .slick-header-column { @@ -23,7 +24,7 @@ classes should alter those! .slick-row { position: absolute; background: white; - border: 0px; + border: 0; line-height: 22px; } @@ -98,14 +99,14 @@ classes should alter those! to { box-shadow: none; } } -.grid-canvas *:last-child{ - border-right: 0px !important; +.grid-canvas .slick-cell:first-child{ + border-left: 0; } .slick-viewport .fa { color: #004849; line-height: 22px; - margin-top: 0px !important; + margin-top: 0 !important; width: 12px; height: 12px; float: left; @@ -115,7 +116,7 @@ classes should alter those! .slick-viewport .icon { color: #004849; line-height: 24px; - margin-top: 0px !important; + margin-top: 0 !important; width: 12px; height: 12px; float: left; @@ -148,9 +149,11 @@ classes should alter those! } .slick-cell, .slick-headerrow-column { - border-right: 1px solid #c7d2d7; + border-right: 0; + border-top: 0; + border-left: 1px solid #c7d2d7; border-bottom: 1px solid #c7d2d7; - padding: 0px 2px 6px 10px; + padding: 0 2px 6px 10px; } div.status-text { 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 5076dc8104..a1301d473e 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 @@ -505,6 +505,21 @@ nf.Canvas = (function () { }; updateFlowStatusContainerSize(); + // listen for events to go to components + $('body').on('GoTo:Component', function (e, item) { + nf.CanvasUtils.showComponent(item.parentGroupId, item.id); + }); + + // listen for events to go to process groups + $('body').on('GoTo:ProcessGroup', function (e, item) { + nf.CanvasUtils.enterGroup(item.id).done(function () { + nf.CanvasUtils.getSelection().classed('selected', false); + + // inform Angular app that values have changed + nf.ng.Bridge.digest(); + }); + }); + // listen for browser resize events to reset the graph size $(window).on('resize', function (e) { if (e.target === window) { diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js index c6932971e9..19ea71e971 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-policy-management.js @@ -339,43 +339,16 @@ nf.PolicyManagement = (function () { // policy type listing $('#policy-type-list').combo({ - options: [{ - text: 'view the user interface', - value: 'flow', - description: 'Allows users to view the user interface' - }, { - text: 'access the controller', - value: 'controller', - description: 'Allows users to view/modify the controller including Reporting Tasks, Controller Services, and Nodes in the Cluster' - }, { - text: 'query provenance', - value: 'provenance', - description: 'Allows users to submit a Provenance Search and request Event Lineage' - }, { - text: 'access all policies', - value: 'policies', - description: 'Allows users to view/modify the policies for all components' - }, { - text: 'access users/user groups', - value: 'tenants', - description: 'Allows users to view/modify the users and user groups' - }, { - text: 'retrieve site-to-site details', - value: 'site-to-site', - description: 'Allows other NiFi instances to retrieve Site-To-Site details of this NiFi' - }, { - text: 'view system diagnostics', - value: 'system', - description: 'Allows users to view System Diagnostics' - }, { - text: 'proxy user requests', - value: 'proxy', - description: 'Allows proxy machines to send requests on the behalf of others' - }, { - text: 'access counters', - value: 'counters', - description: 'Allows users to view/modify Counters' - }], + options: [ + nf.Common.getPolicyTypeListing('flow'), + nf.Common.getPolicyTypeListing('controller'), + nf.Common.getPolicyTypeListing('provenance'), + nf.Common.getPolicyTypeListing('policies'), + nf.Common.getPolicyTypeListing('tenants'), + nf.Common.getPolicyTypeListing('site-to-site'), + nf.Common.getPolicyTypeListing('system'), + nf.Common.getPolicyTypeListing('proxy'), + nf.Common.getPolicyTypeListing('counters')], select: function (option) { if (initialized) { // record the policy type diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js index 9dcf7d3677..5d7054cbf2 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js @@ -77,7 +77,45 @@ $(document).ready(function () { nf.Common = (function () { // interval for cancelling token refresh when necessary var tokenRefreshInterval = null; - + + var policyTypeListing = [{ + text: 'view the user interface', + value: 'flow', + description: 'Allows users to view the user interface' + }, { + text: 'access the controller', + value: 'controller', + description: 'Allows users to view/modify the controller including Reporting Tasks, Controller Services, and Nodes in the Cluster' + }, { + text: 'query provenance', + value: 'provenance', + description: 'Allows users to submit a Provenance Search and request Event Lineage' + }, { + text: 'access all policies', + value: 'policies', + description: 'Allows users to view/modify the policies for all components' + }, { + text: 'access users/user groups', + value: 'tenants', + description: 'Allows users to view/modify the users and user groups' + }, { + text: 'retrieve site-to-site details', + value: 'site-to-site', + description: 'Allows other NiFi instances to retrieve Site-To-Site details of this NiFi' + }, { + text: 'view system diagnostics', + value: 'system', + description: 'Allows users to view System Diagnostics' + }, { + text: 'proxy user requests', + value: 'proxy', + description: 'Allows proxy machines to send requests on the behalf of others' + }, { + text: 'access counters', + value: 'counters', + description: 'Allows users to view/modify Counters' + }]; + return { ANONYMOUS_USER_TEXT: 'Anonymous user', @@ -652,12 +690,12 @@ nf.Common = (function () { formatValue: function (value) { if (nf.Common.isDefinedAndNotNull(value)) { if (value === '') { - return 'Empty string previously set'; + return 'Empty string set'; } else { return nf.Common.escapeHtml(value); } } else { - return 'No value previously set'; + return 'No value set'; } }, @@ -1052,10 +1090,10 @@ nf.Common = (function () { if (!nf.Common.isDefinedAndNotNull(rawDateTime)) { return new Date(); } - if (rawDateTime === 'No value previously set') { + if (rawDateTime === 'No value set') { return new Date(); } - if (rawDateTime === 'Empty string previously set') { + if (rawDateTime === 'Empty string set') { return new Date(); } @@ -1271,6 +1309,13 @@ nf.Common = (function () { } }); return formattedBulletinEntities; + }, + + getPolicyTypeListing: function (value) { + var nest = d3.nest() + .key(function(d) { return d.value; }) + .map(policyTypeListing, d3.map); + return nest.get(value)[0]; } }; }()); diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js index 1656050aa0..4a1f78de2a 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users-table.js @@ -469,6 +469,238 @@ nf.UsersTable = (function () { }); }; + /** + * Initializes the user policies dialog. + */ + var initUserPoliciesDialog = function () { + $('#user-policies-dialog').modal({ + headerText: 'User Policies', + buttons: [{ + buttonText: 'Close', + color: { + base: '#728E9B', + hover: '#004849', + text: '#ffffff' + }, + handler: { + click: function () { + $('#user-policies-dialog').modal('hide'); + } + } + }] + }); + }; + + /** + * Generates a human readable global policy strung. + * + * @param dataContext + * @returns {string} + */ + var globalResourceParser = function (dataContext) { + return 'Global policy to ' + + nf.Common.getPolicyTypeListing(nf.Common.substringAfterFirst(dataContext.component.resource, '/')).text; + }; + + /** + * Generates a human readable component policy string. + * + * @param dataContext + * @returns {string} + */ + var componentResourceParser = function (dataContext) { + var resource = dataContext.component.resource; + var policyLabel = ''; + + //determine policy type + if (resource.startsWith('/policies')) { + resource = nf.Common.substringAfterFirst(resource, '/policies'); + policyLabel += 'Admin policy for '; + } else if (resource.startsWith('/data-transfer')) { + resource = nf.Common.substringAfterFirst(resource, '/data-transfer'); + policyLabel += 'Site to site policy for '; + } else if (resource.startsWith('/data')) { + resource = nf.Common.substringAfterFirst(resource, '/data'); + policyLabel += 'Data policy for '; + } else { + policyLabel += 'Component policy for '; + } + + if (resource.startsWith('/processors')) { + policyLabel += 'processor '; + } else if (resource.startsWith('/controller-services')) { + policyLabel += 'controller service '; + } else if (resource.startsWith('/funnels')) { + policyLabel += 'funnel '; + } else if (resource.startsWith('/input-ports')) { + policyLabel += 'input port '; + } else if (resource.startsWith('/labels')) { + policyLabel += 'label '; + } else if (resource.startsWith('/output-ports')) { + policyLabel += 'output port '; + } else if (resource.startsWith('/process-groups')) { + policyLabel += 'process group '; + } else if (resource.startsWith('/remote-process-groups')) { + policyLabel += 'remote process group '; + } else if (resource.startsWith('/reporting-tasks')) { + policyLabel += 'reporting task '; + } else if (resource.startsWith('/templates')) { + policyLabel += 'template '; + } + + if (dataContext.component.componentReference.permissions.canRead === true) { + policyLabel += '' + dataContext.component.componentReference.component.name + ''; + } else { + policyLabel += '' + dataContext.component.componentReference.id + '' + } + + return policyLabel; + }; + + /** + * Initializes the user policies table. + */ + var initUserPoliciesTable = function () { + + // function for formatting the human readable name of the policy + var policyDisplayNameFormatter = function (row, cell, value, columnDef, dataContext) { + // if the user has permission to the policy + if (dataContext.permissions.canRead === true) { + // check if Global policy + if (nf.Common.isUndefinedOrNull(dataContext.component.componentReference)) { + return globalResourceParser(dataContext); + } + // not a global policy... check if user has access to the component reference + return componentResourceParser(dataContext); + } else { + return '' + dataContext.id + ''; + } + }; + + // function for formatting the actions column + var actionsFormatter = function (row, cell, value, columnDef, dataContext) { + var markup = ''; + + if (dataContext.permissions.canRead === true) { + if (nf.Common.isDefinedAndNotNull(dataContext.component.componentReference)) { + if (dataContext.component.resource.indexOf('/processors') >= 0) { + markup += '
'; + } else if (dataContext.component.resource.indexOf('/controller-services') >= 0) { + //TODO: implement go to for CS + } else if (dataContext.component.resource.indexOf('/funnels') >= 0) { + markup += '
'; + } else if (dataContext.component.resource.indexOf('/input-ports') >= 0) { + markup += '
'; + } else if (dataContext.component.resource.indexOf('/labels') >= 0) { + markup += '
'; + } else if (dataContext.component.resource.indexOf('/output-ports') >= 0) { + markup += '
'; + } else if (dataContext.component.resource.indexOf('/process-groups') >= 0) { + markup += '
'; + } else if (dataContext.component.resource.indexOf('/remote-process-groups') >= 0) { + markup += '
'; + } else if (dataContext.component.resource.indexOf('/reporting-tasks') >= 0) { + //TODO: implement go to for RT + } else if (dataContext.component.resource.indexOf('/templates') >= 0) { + //TODO: implement go to for Templates + } + } + } + + return markup; + }; + + // function for formatting the action column + var actionFormatter = function (row, cell, value, columnDef, dataContext) { + var markup = ''; + + if (dataContext.permissions.canRead === true) { + markup += dataContext.component.action; + } + + return markup; + }; + + var userPoliciesColumns = [ + {id: 'policy', name: 'Policy', sortable: true, resizable: true, formatter: policyDisplayNameFormatter, width: 150}, + {id: 'action', name: 'Action', sortable: true, resizable: false, formatter: actionFormatter, width: 50} + ]; + + // add the actions if we're in the shell + if (top !== window) { + userPoliciesColumns.push({id: 'actions', name: ' ', sortable: false, resizable: false, formatter: actionsFormatter, width: 25}); + } + + var userPoliciesOptions = { + forceFitColumns: true, + enableTextSelectionOnCells: true, + enableCellNavigation: true, + enableColumnReorder: false, + autoEdit: false + }; + + // initialize the dataview + var userPoliciesData = new Slick.Data.DataView({ + inlineFilters: false + }); + userPoliciesData.setItems([]); + + // initialize the sort + userPolicySort({ + columnId: 'policy', + sortAsc: true + }, userPoliciesData); + + // initialize the grid + var userPoliciesGrid = new Slick.Grid('#user-policies-table', userPoliciesData, userPoliciesColumns, userPoliciesOptions); + userPoliciesGrid.setSelectionModel(new Slick.RowSelectionModel()); + userPoliciesGrid.registerPlugin(new Slick.AutoTooltips()); + userPoliciesGrid.setSortColumn('policy', true); + userPoliciesGrid.onSort.subscribe(function (e, args) { + userPolicySort({ + columnId: args.sortCol.id, + sortAsc: args.sortAsc + }, userPoliciesData); + }); + + // configure a click listener + userPoliciesGrid.onClick.subscribe(function (e, args) { + var target = $(e.target); + + // get the node at this row + var item = userPoliciesData.getItem(args.row); + + // determine the desired action + if (userPoliciesGrid.getColumns()[args.cell].id === 'actions') { + if (target.hasClass('go-to-component')) { + parent.$('body').trigger('GoTo:Component', { + id: item.component.componentReference.id, + parentGroupId: item.component.componentReference.parentGroupId + }); + parent.$('#shell-close-button').click(); + } else if (target.hasClass('go-to-process-group')) { + parent.$('body').trigger('GoTo:ProcessGroup', { + id: item.component.componentReference.id + }); + parent.$('#shell-close-button').click(); + } + } + }); + + // wire up the dataview to the grid + userPoliciesData.onRowCountChanged.subscribe(function (e, args) { + userPoliciesGrid.updateRowCount(); + userPoliciesGrid.render(); + }); + userPoliciesData.onRowsChanged.subscribe(function (e, args) { + userPoliciesGrid.invalidateRows(args.rows); + userPoliciesGrid.render(); + }); + + // hold onto an instance of the grid + $('#user-policies-table').data('gridInstance', userPoliciesGrid); + }; + /** * Initializes the processor list. */ @@ -524,6 +756,10 @@ nf.UsersTable = (function () { markup += '
'; } + if (!nf.Common.isEmpty(dataContext.component.accessPolicies)) { + markup += '
'; + } + return markup; }; @@ -553,7 +789,7 @@ nf.UsersTable = (function () { usersData.setFilter(filter); // initialize the sort - sort({ + userSort({ columnId: 'identity', sortAsc: true }, usersData); @@ -564,7 +800,7 @@ nf.UsersTable = (function () { usersGrid.registerPlugin(new Slick.AutoTooltips()); usersGrid.setSortColumn('identity', true); usersGrid.onSort.subscribe(function (e, args) { - sort({ + userSort({ columnId: args.sortCol.id, sortAsc: args.sortAsc }, usersData); @@ -581,6 +817,8 @@ nf.UsersTable = (function () { if (usersGrid.getColumns()[args.cell].id === 'actions') { if (target.hasClass('edit-user')) { editUser(item); + } else if (target.hasClass('view-user-policies')) { + viewUserPolicies(item); } else if (target.hasClass('delete-user')) { deleteUser(item); } @@ -613,7 +851,7 @@ nf.UsersTable = (function () { * @param {object} sortDetails * @param {object} data */ - var sort = function (sortDetails, data) { + var userSort = function (sortDetails, data) { // defines a function for sorting var comparer = function (a, b) { if(a.permissions.canRead && b.permissions.canRead) { @@ -636,6 +874,68 @@ nf.UsersTable = (function () { data.sort(comparer, sortDetails.sortAsc); }; + /** + * Sorts the specified data using the specified sort details. + * + * @param {object} sortDetails + * @param {object} data + */ + var userPolicySort = function (sortDetails, data) { + // defines a function for sorting + var comparer = function (a, b) { + if(a.permissions.canRead && b.permissions.canRead) { + if (sortDetails.columnId === 'action') { + var aString = nf.Common.isDefinedAndNotNull(a.component[sortDetails.columnId]) ? a.component[sortDetails.columnId] : ''; + var bString = nf.Common.isDefinedAndNotNull(b.component[sortDetails.columnId]) ? b.component[sortDetails.columnId] : ''; + return aString === bString ? 0 : aString > bString ? 1 : -1; + } else if (sortDetails.columnId === 'policy') { + var aString = ''; + var bString = ''; + + // if the user has permission to the policy + if (a.permissions.canRead === true) { + // check if Global policy + if (nf.Common.isUndefinedOrNull(a.component.componentReference)) { + aString = globalResourceParser(a); + } else { + // not a global policy... check if user has access to the component reference + aString = componentResourceParser(a); + } + } else { + aString = a.id; + } + + // if the user has permission to the policy + if (b.permissions.canRead === true) { + // check if Global policy + if (nf.Common.isUndefinedOrNull(b.component.componentReference)) { + bString = globalResourceParser(b); + }else { + // not a global policy... check if user has access to the component reference + bString = componentResourceParser(b); + } + } else { + bString = b.id; + } + + return aString === bString ? 0 : aString > bString ? 1 : -1; + } + } else { + if (!a.permissions.canRead && !b.permissions.canRead){ + return 0; + } + if(a.permissions.canRead){ + return 1; + } else { + return -1; + } + } + }; + + // perform the sort + data.sort(comparer, sortDetails.sortAsc); + }; + /** * Get the text out of the filter field. If the filter field doesn't * have any text it will contain the text 'filter list' so this method @@ -814,9 +1114,43 @@ nf.UsersTable = (function () { $('#user-delete-dialog').modal('show'); }; + /** + * Open's a view of the specified user's policies. + * + * @argument {object} user The user item + */ + var viewUserPolicies = function (user) { + var userPoliciesGrid = $('#user-policies-table').data('gridInstance'); + var userPoliciesData = userPoliciesGrid.getData(); + + // begin the update + userPoliciesData.beginUpdate(); + + // set the rows + if (nf.Common.isDefinedAndNotNull(user.component.accessPolicies)) { + userPoliciesData.setItems(user.component.accessPolicies); + } + + $('#policies-dialog-user-name').text(user.component.identity); + + // end the update + userPoliciesData.endUpdate(); + + // re-sort and clear selection after updating + userPoliciesData.reSort(); + userPoliciesGrid.invalidate(); + userPoliciesGrid.getSelectionModel().setSelectedRows([]); + + // show the dialog + $('#user-policies-dialog').modal('show'); + userPoliciesGrid.resizeCanvas(); + }; + return { init: function () { initUserDialog(); + initUserPoliciesDialog(); + initUserPoliciesTable(); initUserDeleteDialog(); initUsersTable(); @@ -852,7 +1186,7 @@ nf.UsersTable = (function () { }, /** - * Load the processor status table. + * Load the users table. */ loadUsersTable: function () { var users = $.ajax({ diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js index 8e7c0059a7..34476a2d3d 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/users/nf-users.js @@ -145,6 +145,28 @@ nf.Users = (function () { $('#users-header-text').text(countersTitle); }).fail(nf.Common.handleAjaxError); }); + + $(window).on('resize', function (e) { + // resize dialogs when appropriate + var dialogs = $('.dialog'); + for (var i = 0, len = dialogs.length; i < len; i++) { + if ($(dialogs[i]).is(':visible')){ + setTimeout(function(dialog){ + dialog.modal('resize'); + }, 50, $(dialogs[i])); + } + } + + // resize grids when appropriate + var gridElements = $('*[class*="slickgrid_"]'); + for (var j = 0, len = gridElements.length; j < len; j++) { + if ($(gridElements[j]).is(':visible')){ + setTimeout(function(gridElement){ + gridElement.data('gridInstance').resizeCanvas(); + }, 50, $(gridElements[j])); + } + } + }); }); }); }