NIFI-2926: add policy action item to the user table and add user centric policy dialog with user policy listing table compolete with GoTo action.

This closes #1188.
This commit is contained in:
Scott Aslan 2016-11-11 15:04:20 -05:00 committed by Mark Payne
parent 59fea1cb4e
commit 8f928e5d6e
36 changed files with 923 additions and 123 deletions

View File

@ -41,7 +41,7 @@ public interface Authorizable {
/**
* The Resource for this Authorizable.
*
* @return the parent resource
* @return the resource
*/
Resource getResource();

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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<AccessPolicyEntity> getAccessPolicies() {

View File

@ -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;
}
}

View File

@ -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 <code>Connectable</code>

View File

@ -371,8 +371,6 @@ public abstract class AbstractConfiguredComponent implements ConfigurableCompone
public abstract void verifyModifiable() throws IllegalStateException;
protected abstract String getProcessGroupIdentifier();
/**
*
*/

View File

@ -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();

View File

@ -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();

View File

@ -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<Relationship> getRelationships() {
return relationships;

View File

@ -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
*

View File

@ -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();

View File

@ -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;
* <p>
* MUST BE THREAD-SAFE</p>
*/
public interface ProcessGroup extends Authorizable, Positionable {
public interface ProcessGroup extends ComponentAuthorizable, Positionable {
/**
* Predicate for filtering schedulable Processors.

View File

@ -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();

View File

@ -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();
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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();

View File

@ -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();

View File

@ -60,6 +60,11 @@ public class MockProcessGroup implements ProcessGroup {
return null;
}
@Override
public String getProcessGroupIdentifier() {
return null;
}
@Override
public void setParent(final ProcessGroup group) {

View File

@ -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<TenantEntity> users = accessPolicy.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet());
final Set<TenantEntity> 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<AccessPolicy> policies = userGroupDAO.getAccessPoliciesForUserGroup(userGroupDTO.getId());
final RevisionUpdate<UserGroupDTO> snapshot = updateComponent(revision,
userGroupsAuthorizable,
() -> userGroupDAO.updateUserGroup(userGroupDTO),
userGroup -> dtoFactory.createUserGroupDto(userGroup, userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet())));
userGroup -> {
final Set<TenantEntity> tenantEntities = userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet());
final Set<AccessPolicySummaryEntity> 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<TenantEntity> users = userGroup != null ? userGroup.getUsers().stream()
.map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) :
null;
.map(mapUserIdToTenantEntity()).collect(Collectors.toSet()) : null;
final Set<AccessPolicySummaryEntity> 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<TenantEntity> userGroups = accessPolicy != null ? accessPolicy.getGroups().stream().map(mapUserGroupIdToTenantEntity()).collect(Collectors.toSet()) : null;
final Set<TenantEntity> 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<TenantEntity> tenantEntities = newUserGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet());
final Set<AccessPolicySummaryEntity> 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<TenantEntity> users = userGroup.getUsers().stream().map(mapUserIdToTenantEntity()).collect(Collectors.toSet());
return entityFactory.createUserGroupEntity(dtoFactory.createUserGroupDto(userGroup, users), userGroupRevision,
dtoFactory.createPermissionsDto(authorizableLookup.getTenant()));
final Set<AccessPolicySummaryEntity> policyEntities = userGroupDAO.getAccessPoliciesForUserGroup(userGroup.getIdentifier()).stream()
.map(ap -> createAccessPolicySummaryEntity(ap)).collect(Collectors.toSet());
return entityFactory.createUserGroupEntity(dtoFactory.createUserGroupDto(userGroup, users, policyEntities), userGroupRevision, permissions);
}
@Override

View File

@ -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<TenantEntity> users) {
public UserGroupDTO createUserGroupDto(final Group userGroup, Set<TenantEntity> users, final Set<AccessPolicySummaryEntity> accessPolicies) {
if (userGroup == null) {
return null;
}
// convert to access policies to handle backward compatibility due to incorrect
// type in the UserGroupDTO
final Set<AccessPolicyEntity> 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<TenantEntity> userGroups, Set<TenantEntity> users) {
public AccessPolicyDTO createAccessPolicyDto(final AccessPolicy accessPolicy, final Set<TenantEntity> userGroups,
final Set<TenantEntity> 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;
}

View File

@ -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);

View File

@ -62,6 +62,14 @@ public interface UserGroupDAO {
*/
Set<AccessPolicy> 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<AccessPolicy> getAccessPoliciesForUserGroup(String userGroupId);
/**
* Gets all user groups.
*

View File

@ -277,6 +277,16 @@ public class StandardPolicyBasedAuthorizerDAO implements AccessPolicyDAO, UserGr
.collect(Collectors.toSet());
}
@Override
public Set<AccessPolicy> 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<Group> getUserGroups() {
return authorizer.getGroups();

View File

@ -32,6 +32,7 @@
<link rel="stylesheet" href="js/jquery/slickgrid/css/slick-default-theme.css" type="text/css" />
<link rel="stylesheet" href="fonts/flowfont/flowfont.css" type="text/css" />
<link rel="stylesheet" href="assets/font-awesome/css/font-awesome.min.css" type="text/css" />
<script type="text/javascript" src="js/d3/d3.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery/ui-smoothness/jquery-ui-1.10.4.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery.base64.js"></script>
@ -64,6 +65,7 @@
<jsp:include page="/WEB-INF/partials/banners-utility.jsp"/>
<jsp:include page="/WEB-INF/partials/ok-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/users/user-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/users/user-policies-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/users/user-delete-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/users/users-content.jsp"/>
</body>

View File

@ -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" %>
<div id="user-policies-dialog" class="hidden large-dialog">
<div class="dialog-content">
<div class="setting">
<div class="setting-name">User</div>
<div class="setting-field">
<div id="policies-dialog-user-name"></div>
</div>
</div>
<div id="user-policy-message" title="Some policies may be inherited by descendant components unless explicitly overridden.">
Some policies may be inherited by descendant components unless explicitly overridden.
</div>
<div id="user-policies-table"></div>
</div>
</div>

View File

@ -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 {

View File

@ -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 {

View File

@ -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) {

View File

@ -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

View File

@ -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 '<span class="blank" style="font-size: 13px; padding-top: 2px;">Empty string previously set</span>';
return '<span class="blank" style="font-size: 13px; padding-top: 2px;">Empty string set</span>';
} else {
return nf.Common.escapeHtml(value);
}
} else {
return '<span class="unset" style="font-size: 13px; padding-top: 2px;">No value previously set</span>';
return '<span class="unset" style="font-size: 13px; padding-top: 2px;">No value set</span>';
}
},
@ -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];
}
};
}());

View File

@ -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 += '<span style="font-weight: 500">' + dataContext.component.componentReference.component.name + '</span>';
} else {
policyLabel += '<span class="unset">' + dataContext.component.componentReference.id + '</span>'
}
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 '<span class="unset">' + dataContext.id + '</span>';
}
};
// 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 += '<div title="Go To" class="pointer go-to-component fa fa-long-arrow-right" style="float: left;"></div>';
} else if (dataContext.component.resource.indexOf('/controller-services') >= 0) {
//TODO: implement go to for CS
} else if (dataContext.component.resource.indexOf('/funnels') >= 0) {
markup += '<div title="Go To" class="pointer go-to-component fa fa-long-arrow-right" style="float: left;"></div>';
} else if (dataContext.component.resource.indexOf('/input-ports') >= 0) {
markup += '<div title="Go To" class="pointer go-to-component fa fa-long-arrow-right" style="float: left;"></div>';
} else if (dataContext.component.resource.indexOf('/labels') >= 0) {
markup += '<div title="Go To" class="pointer go-to-component fa fa-long-arrow-right" style="float: left;"></div>';
} else if (dataContext.component.resource.indexOf('/output-ports') >= 0) {
markup += '<div title="Go To" class="pointer go-to-component fa fa-long-arrow-right" style="float: left;"></div>';
} else if (dataContext.component.resource.indexOf('/process-groups') >= 0) {
markup += '<div title="Go To" class="pointer go-to-process-group fa fa-long-arrow-right" style="float: left;"></div>';
} else if (dataContext.component.resource.indexOf('/remote-process-groups') >= 0) {
markup += '<div title="Go To" class="pointer go-to-component fa fa-long-arrow-right" style="float: left;"></div>';
} 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: '&nbsp;', 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 += '<div title="Remove" class="pointer delete-user fa fa-trash"></div>';
}
if (!nf.Common.isEmpty(dataContext.component.accessPolicies)) {
markup += '<div title="View User Policies" class="pointer view-user-policies fa fa-key" style="margin-left: 3px;"></div>';
}
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({

View File

@ -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]));
}
}
});
});
});
}