NIFI-4436:

- Code clean up.
- Improved error handling.
- Minor UX improvements.
- Adding message to indicate that variables do not support sensitive values.
- Preventing a user from changing the flow version to the current version.
- Only presenting buckets a user has appropriate permissions to.
- Adding basic auditing to the version control actions.
This commit is contained in:
Matt Gilman 2017-12-06 10:47:28 -05:00 committed by Bryan Bende
parent 014c542f48
commit db2cc9fec1
No known key found for this signature in database
GPG Key ID: A0DDA9ED50711C39
25 changed files with 502 additions and 203 deletions

View File

@ -21,18 +21,34 @@ package org.apache.nifi.action;
*/ */
public enum Operation { public enum Operation {
Add, Add("Add"),
Remove, Remove("Remove"),
Paste, Paste("Paste"),
Configure, Configure("Configure"),
Move, Move("Move"),
Disconnect, Disconnect("Disconnect"),
Connect, Connect("Connect"),
Start, Start("Start"),
Stop, Stop("Stop"),
Enable, Enable("Enable"),
Disable, Disable("Disable"),
Batch, Batch("Batch"),
Purge, Purge("Purge"),
ClearState; ClearState("Clear State"),
StartVersionControl("Start Version Control"),
StopVersionControl("Stop Version Control"),
CommitLocalChanges("Commit Local Changes"),
RevertLocalChanges("Revert Local Changes"),
ChangeVersion("Change Version");
private final String label;
Operation(String label) {
this.label = label;
}
@Override
public String toString() {
return label;
}
} }

View File

@ -219,8 +219,8 @@ public class StandardActionDAO implements ActionDAO {
statement.setString(1, StringUtils.left(action.getUserIdentity(), 4096)); statement.setString(1, StringUtils.left(action.getUserIdentity(), 4096));
statement.setString(2, action.getSourceId()); statement.setString(2, action.getSourceId());
statement.setString(3, StringUtils.left(action.getSourceName(), 1000)); statement.setString(3, StringUtils.left(action.getSourceName(), 1000));
statement.setString(4, action.getSourceType().toString()); statement.setString(4, action.getSourceType().name());
statement.setString(5, action.getOperation().toString()); statement.setString(5, action.getOperation().name());
statement.setTimestamp(6, new java.sql.Timestamp(action.getTimestamp().getTime())); statement.setTimestamp(6, new java.sql.Timestamp(action.getTimestamp().getTime()));
// insert the action // insert the action

View File

@ -17,6 +17,7 @@
package org.apache.nifi.web.api.entity; package org.apache.nifi.web.api.entity;
import org.apache.nifi.web.api.dto.BucketDTO; import org.apache.nifi.web.api.dto.BucketDTO;
import org.apache.nifi.web.api.dto.PermissionsDTO;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
@ -26,8 +27,17 @@ import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "bucketEntity") @XmlRootElement(name = "bucketEntity")
public class BucketEntity extends Entity { public class BucketEntity extends Entity {
private String id;
private BucketDTO bucket; private BucketDTO bucket;
private PermissionsDTO permissions;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public BucketDTO getBucket() { public BucketDTO getBucket() {
return bucket; return bucket;
@ -36,4 +46,12 @@ public class BucketEntity extends Entity {
public void setBucket(BucketDTO bucket) { public void setBucket(BucketDTO bucket) {
this.bucket = bucket; this.bucket = bucket;
} }
public PermissionsDTO getPermissions() {
return permissions;
}
public void setPermissions(PermissionsDTO permissions) {
this.permissions = permissions;
}
} }

View File

@ -22,13 +22,13 @@ import java.util.Set;
/** /**
* A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a set of RegistryEntity's. * A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a set of RegistryEntity's.
*/ */
@XmlRootElement(name = "registriesEntity") @XmlRootElement(name = "registryClientsEntity")
public class RegistriesEntity extends Entity { public class RegistriesEntity extends Entity {
private Set<RegistryEntity> registries; private Set<RegistryEntity> registries;
/** /**
* @return collection of LabelEntity's that are being serialized * @return collection of RegistryEntity's that are being serialized
*/ */
public Set<RegistryEntity> getRegistries() { public Set<RegistryEntity> getRegistries() {
return registries; return registries;

View File

@ -0,0 +1,38 @@
/*
* 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 org.apache.nifi.web.api.dto.RegistryDTO;
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 a RegistryDTO.
*/
@XmlRootElement(name = "registryClientEntity")
public class RegistryClientEntity extends ComponentEntity {
private RegistryDTO component;
public RegistryDTO getComponent() {
return component;
}
public void setComponent(RegistryDTO component) {
this.component = component;
}
}

View File

@ -0,0 +1,41 @@
/*
* 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 javax.xml.bind.annotation.XmlRootElement;
import java.util.Set;
/**
* A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a set of RegistryClientEntity's.
*/
@XmlRootElement(name = "registryClientsEntity")
public class RegistryClientsEntity extends Entity {
private Set<RegistryClientEntity> registries;
/**
* @return collection of RegistryClientEntity's that are being serialized
*/
public Set<RegistryClientEntity> getRegistries() {
return registries;
}
public void setRegistries(Set<RegistryClientEntity> registries) {
this.registries = registries;
}
}

View File

@ -24,16 +24,15 @@ 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 a RegistryDTO. * 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 a RegistryDTO.
*/ */
@XmlRootElement(name = "registryEntity") @XmlRootElement(name = "registryEntity")
public class RegistryEntity extends ComponentEntity { public class RegistryEntity {
private RegistryDTO component; private RegistryDTO registry;
public RegistryDTO getRegistry() {
public RegistryDTO getComponent() { return registry;
return component;
} }
public void setComponent(RegistryDTO component) { public void setRegistry(RegistryDTO registry) {
this.component = component; this.registry = registry;
} }
} }

View File

@ -28,7 +28,10 @@ import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.service.ControllerServiceState; import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.registry.flow.VersionControlInformation;
import org.apache.nifi.web.api.dto.ProcessGroupDTO; import org.apache.nifi.web.api.dto.ProcessGroupDTO;
import org.apache.nifi.web.api.dto.VariableRegistryDTO;
import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
import org.apache.nifi.web.dao.ProcessGroupDAO; import org.apache.nifi.web.dao.ProcessGroupDAO;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Around;
@ -39,6 +42,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.concurrent.Future;
/** /**
* Audits process group creation/removal and configuration changes. * Audits process group creation/removal and configuration changes.
@ -173,10 +177,13 @@ public class ProcessGroupAuditor extends NiFiAuditor {
* @throws Throwable ex * @throws Throwable ex
*/ */
@Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && " @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+ "execution(void scheduleComponents(java.lang.String, org.apache.nifi.controller.ScheduledState, java.util.Set)) && " + "execution(java.util.concurrent.Future<Void> scheduleComponents(java.lang.String, org.apache.nifi.controller.ScheduledState, java.util.Set)) && "
+ "args(groupId, state)") + "args(groupId, state)")
public void scheduleComponentsAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ScheduledState state) throws Throwable { public Future<Void> scheduleComponentsAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ScheduledState state) throws Throwable {
final Operation operation; final Operation operation;
final Future<Void> result = (Future<Void>) proceedingJoinPoint.proceed();
// determine the running state // determine the running state
if (ScheduledState.RUNNING.equals(state)) { if (ScheduledState.RUNNING.equals(state)) {
operation = Operation.Start; operation = Operation.Start;
@ -184,7 +191,9 @@ public class ProcessGroupAuditor extends NiFiAuditor {
operation = Operation.Stop; operation = Operation.Stop;
} }
saveUpdateAction(proceedingJoinPoint, groupId, operation); saveUpdateAction(NiFiUserUtils.getNiFiUser(), groupId, operation);
return result;
} }
@ -193,52 +202,118 @@ public class ProcessGroupAuditor extends NiFiAuditor {
* *
* @param proceedingJoinPoint join point * @param proceedingJoinPoint join point
* @param groupId group id * @param groupId group id
* @param state controller serivce state state * @param state controller service state
* @throws Throwable ex * @throws Throwable ex
*/ */
@Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && " @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+ "execution(java.util.concurrent.Future activateControllerServices(java.lang.String, org.apache.nifi.controller.service.ControllerServiceState, java.util.Set)) && " + "execution(java.util.concurrent.Future<Void> activateControllerServices(java.lang.String, org.apache.nifi.controller.service.ControllerServiceState, java.util.Set)) && "
+ "args(groupId, state)") + "args(groupId, state)")
public void activateControllerServicesAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ControllerServiceState state) throws Throwable { public Future<Void> activateControllerServicesAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId, ControllerServiceState state) throws Throwable {
final Operation operation;
final Future<Void> result = (Future<Void>) proceedingJoinPoint.proceed();
// determine the service state // determine the service state
final Operation operation;
if (ControllerServiceState.ENABLED.equals(state)) { if (ControllerServiceState.ENABLED.equals(state)) {
operation = Operation.Enable; operation = Operation.Enable;
} else { } else {
operation = Operation.Disable; operation = Operation.Disable;
} }
saveUpdateAction(proceedingJoinPoint, groupId, operation); saveUpdateAction(NiFiUserUtils.getNiFiUser(), groupId, operation);
return result;
} }
/** /**
* Audits the update of process group variable registry. * Audits the update of process group variable registry.
* *
* @param proceedingJoinPoint join point * @param proceedingJoinPoint join point
* @param groupId group id * @param user the user performing the action
* @param variableRegistry variable registry
* @throws Throwable ex * @throws Throwable ex
*/ */
@Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && " @Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+ "execution(org.apache.nifi.groups.ProcessGroup updateVariableRegistry(org.apache.nifi.web.api.dto.VariableRegistryDTO)) && " + "execution(org.apache.nifi.groups.ProcessGroup updateVariableRegistry(org.apache.nifi.authorization.user.NiFiUser, org.apache.nifi.web.api.dto.VariableRegistryDTO)) && "
+ "args(groupId)") + "args(user, variableRegistry)")
public void updateVariableRegistryAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId) throws Throwable { public ProcessGroup updateVariableRegistryAdvice(final ProceedingJoinPoint proceedingJoinPoint, final NiFiUser user, final VariableRegistryDTO variableRegistry) throws Throwable {
final Operation operation = Operation.Configure; final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
saveUpdateAction(proceedingJoinPoint, groupId, operation);
saveUpdateAction(user, variableRegistry.getProcessGroupId(), Operation.Configure);
return updatedProcessGroup;
} }
@Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+ "execution(org.apache.nifi.groups.ProcessGroup updateProcessGroupFlow(..))")
public ProcessGroup updateProcessGroupFlowAdvice(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
final Object[] args = proceedingJoinPoint.getArgs();
final String groupId = (String) args[0];
final NiFiUser user = (NiFiUser) args[1];
final ProcessGroupDAO processGroupDAO = getProcessGroupDAO();
final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
final VersionControlInformation vci = processGroup.getVersionControlInformation();
private void saveUpdateAction(final ProceedingJoinPoint proceedingJoinPoint, final String groupId, final Operation operation) throws Throwable { final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
final VersionControlInformation updatedVci = updatedProcessGroup.getVersionControlInformation();
final Operation operation;
if (vci == null) {
operation = Operation.StartVersionControl;
} else {
if (updatedVci == null) {
operation = Operation.StopVersionControl;
} else if (vci.getVersion() == updatedVci.getVersion()) {
operation = Operation.RevertLocalChanges;
} else {
operation = Operation.ChangeVersion;
}
}
saveUpdateAction(user, groupId, operation);
return updatedProcessGroup;
}
@Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+ "execution(org.apache.nifi.groups.ProcessGroup updateVersionControlInformation(..))")
public ProcessGroup updateVersionControlInformationAdvice(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
final VersionControlInformationDTO vciDto = (VersionControlInformationDTO) proceedingJoinPoint.getArgs()[0];
final ProcessGroupDAO processGroupDAO = getProcessGroupDAO();
final ProcessGroup processGroup = processGroupDAO.getProcessGroup(vciDto.getGroupId());
final VersionControlInformation vci = processGroup.getVersionControlInformation();
final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
final Operation operation;
if (vci == null) {
operation = Operation.StartVersionControl;
} else {
operation = Operation.CommitLocalChanges;
}
saveUpdateAction(NiFiUserUtils.getNiFiUser(), vciDto.getGroupId(), operation);
return updatedProcessGroup;
}
@Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+ "execution(org.apache.nifi.groups.ProcessGroup disconnectVersionControl(java.lang.String)) && "
+ "args(groupId)")
public ProcessGroup disconnectVersionControlAdvice(final ProceedingJoinPoint proceedingJoinPoint, final String groupId) throws Throwable {
final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
saveUpdateAction(NiFiUserUtils.getNiFiUser(), groupId, Operation.StopVersionControl);
return updatedProcessGroup;
}
private void saveUpdateAction(final NiFiUser user, final String groupId, final Operation operation) throws Throwable {
ProcessGroupDAO processGroupDAO = getProcessGroupDAO(); ProcessGroupDAO processGroupDAO = getProcessGroupDAO();
ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId); ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
// perform the action
proceedingJoinPoint.proceed();
// get the current user
NiFiUser user = NiFiUserUtils.getNiFiUser();
// if the user was starting/stopping this process group // if the user was starting/stopping this process group
FlowChangeAction action = new FlowChangeAction(); FlowChangeAction action = new FlowChangeAction();
action.setUserIdentity(user.getIdentity()); action.setUserIdentity(user.getIdentity());

View File

@ -16,14 +16,6 @@
*/ */
package org.apache.nifi.web; package org.apache.nifi.web;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import org.apache.nifi.authorization.AuthorizeAccess; import org.apache.nifi.authorization.AuthorizeAccess;
import org.apache.nifi.authorization.RequestAction; import org.apache.nifi.authorization.RequestAction;
import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.NiFiUser;
@ -106,6 +98,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity;
import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity; import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity; import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusEntity; import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
import org.apache.nifi.web.api.entity.RegistryClientEntity;
import org.apache.nifi.web.api.entity.RegistryEntity; import org.apache.nifi.web.api.entity.RegistryEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
@ -124,6 +117,14 @@ import org.apache.nifi.web.api.entity.VersionControlInformationEntity;
import org.apache.nifi.web.api.entity.VersionedFlowEntity; import org.apache.nifi.web.api.entity.VersionedFlowEntity;
import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataEntity; import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataEntity;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
/** /**
* Defines the NiFiServiceFacade interface. * Defines the NiFiServiceFacade interface.
*/ */
@ -1929,7 +1930,7 @@ public interface NiFiServiceFacade {
* @param registryDTO The registry DTO * @param registryDTO The registry DTO
* @return The reporting task DTO * @return The reporting task DTO
*/ */
RegistryEntity createRegistryClient(Revision revision, RegistryDTO registryDTO); RegistryClientEntity createRegistryClient(Revision revision, RegistryDTO registryDTO);
/** /**
* Gets a registry with the specified id. * Gets a registry with the specified id.
@ -1937,14 +1938,14 @@ public interface NiFiServiceFacade {
* @param registryId id * @param registryId id
* @return entity * @return entity
*/ */
RegistryEntity getRegistryClient(String registryId); RegistryClientEntity getRegistryClient(String registryId);
/** /**
* Returns all registry clients. * Returns all registry clients.
* *
* @return registry clients * @return registry clients
*/ */
Set<RegistryEntity> getRegistryClients(); Set<RegistryClientEntity> getRegistryClients();
/** /**
* Gets all registries for the current user. * Gets all registries for the current user.
@ -1991,7 +1992,7 @@ public interface NiFiServiceFacade {
* @param registryDTO the registry dto * @param registryDTO the registry dto
* @return the updated registry registry entity * @return the updated registry registry entity
*/ */
RegistryEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO); RegistryClientEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO);
/** /**
* Deletes the specified registry using the specified revision. * Deletes the specified registry using the specified revision.
@ -2000,7 +2001,7 @@ public interface NiFiServiceFacade {
* @param registryId id * @param registryId id
* @return the deleted registry entity * @return the deleted registry entity
*/ */
RegistryEntity deleteRegistryClient(Revision revision, String registryId); RegistryClientEntity deleteRegistryClient(Revision revision, String registryId);
/** /**
* Verifies the specified registry can be removed. * Verifies the specified registry can be removed.

View File

@ -220,6 +220,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity; import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity; import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusEntity; import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
import org.apache.nifi.web.api.entity.RegistryClientEntity;
import org.apache.nifi.web.api.entity.RegistryEntity; import org.apache.nifi.web.api.entity.RegistryEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
@ -927,7 +928,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(variableRegistryDto.getProcessGroupId()); final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(variableRegistryDto.getProcessGroupId());
final RevisionUpdate<VariableRegistryDTO> snapshot = updateComponent(user, revision, final RevisionUpdate<VariableRegistryDTO> snapshot = updateComponent(user, revision,
processGroupNode, processGroupNode,
() -> processGroupDAO.updateVariableRegistry(variableRegistryDto), () -> processGroupDAO.updateVariableRegistry(user, variableRegistryDto),
processGroup -> dtoFactory.createVariableRegistryDto(processGroup, revisionManager)); processGroup -> dtoFactory.createVariableRegistryDto(processGroup, revisionManager));
final PermissionsDTO permissions = dtoFactory.createPermissionsDto(processGroupNode); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(processGroupNode);
@ -2301,10 +2302,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
@Override @Override
public RegistryEntity createRegistryClient(Revision revision, RegistryDTO registryDTO) { public RegistryClientEntity createRegistryClient(Revision revision, RegistryDTO registryDTO) {
final NiFiUser user = NiFiUserUtils.getNiFiUser(); final NiFiUser user = NiFiUserUtils.getNiFiUser();
// read lock on the containing group
// request claim for component to be created... revision already verified (version == 0) // request claim for component to be created... revision already verified (version == 0)
final RevisionClaim claim = new StandardRevisionClaim(revision); final RevisionClaim claim = new StandardRevisionClaim(revision);
@ -2321,52 +2321,25 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}); });
final FlowRegistry registry = revisionUpdate.getComponent(); final FlowRegistry registry = revisionUpdate.getComponent();
return createRegistryEntity(registry); return createRegistryClientEntity(registry);
} }
@Override @Override
public RegistryEntity getRegistryClient(final String registryId) { public RegistryClientEntity getRegistryClient(final String registryId) {
final FlowRegistry registry = registryDAO.getFlowRegistry(registryId); final FlowRegistry registry = registryDAO.getFlowRegistry(registryId);
return createRegistryEntity(registry); return createRegistryClientEntity(registry);
} }
private RegistryEntity createRegistryEntity(final FlowRegistry flowRegistry) { private RegistryClientEntity createRegistryClientEntity(final FlowRegistry flowRegistry) {
if (flowRegistry == null) { if (flowRegistry == null) {
return null; return null;
} }
final RevisionDTO revision = dtoFactory.createRevisionDTO(revisionManager.getRevision(flowRegistry.getIdentifier()));
final PermissionsDTO permissions = dtoFactory.createPermissionsDto(authorizableLookup.getController());
final RegistryDTO dto = dtoFactory.createRegistryDto(flowRegistry); final RegistryDTO dto = dtoFactory.createRegistryDto(flowRegistry);
final Revision revision = revisionManager.getRevision(dto.getId());
final RegistryEntity entity = new RegistryEntity(); return entityFactory.createRegistryClientEntity(dto, revision, permissions);
entity.setComponent(dto);
entity.setRevision(dtoFactory.createRevisionDTO(revision));
entity.setId(dto.getId());
// User who created it can read/write it.
final PermissionsDTO permissions = new PermissionsDTO();
permissions.setCanRead(true);
permissions.setCanWrite(true);
entity.setPermissions(permissions);
return entity;
}
private BucketEntity createBucketEntity(final Bucket bucket) {
if (bucket == null) {
return null;
}
final BucketDTO dto = new BucketDTO();
dto.setId(bucket.getIdentifier());
dto.setName(bucket.getName());
dto.setDescription(bucket.getDescription());
dto.setCreated(bucket.getCreatedTimestamp());
final BucketEntity entity = new BucketEntity();
entity.setBucket(dto);
return entity;
} }
private VersionedFlowEntity createVersionedFlowEntity(final String registryId, final VersionedFlow versionedFlow) { private VersionedFlowEntity createVersionedFlowEntity(final String registryId, final VersionedFlow versionedFlow) {
@ -2400,23 +2373,40 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
} }
@Override @Override
public Set<RegistryEntity> getRegistryClients() { public Set<RegistryClientEntity> getRegistryClients() {
return registryDAO.getFlowRegistries().stream() return registryDAO.getFlowRegistries().stream()
.map(this::createRegistryEntity) .map(this::createRegistryClientEntity)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@Override @Override
public Set<RegistryEntity> getRegistriesForUser(final NiFiUser user) { public Set<RegistryEntity> getRegistriesForUser(final NiFiUser user) {
return registryDAO.getFlowRegistriesForUser(user).stream() return registryDAO.getFlowRegistriesForUser(user).stream()
.map(this::createRegistryEntity) .map(flowRegistry -> entityFactory.createRegistryEntity(dtoFactory.createRegistryDto(flowRegistry)))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@Override @Override
public Set<BucketEntity> getBucketsForUser(final String registryId, final NiFiUser user) { public Set<BucketEntity> getBucketsForUser(final String registryId, final NiFiUser user) {
return registryDAO.getBucketsForUser(registryId, user).stream() return registryDAO.getBucketsForUser(registryId, user).stream()
.map(this::createBucketEntity) .map(bucket -> {
if (bucket == null) {
return null;
}
final BucketDTO dto = new BucketDTO();
dto.setId(bucket.getIdentifier());
dto.setName(bucket.getName());
dto.setDescription(bucket.getDescription());
dto.setCreated(bucket.getCreatedTimestamp());
final Set<String> authorizedActions = bucket.getAuthorizedActions();
final PermissionsDTO permissions = new PermissionsDTO();
permissions.setCanRead(authorizedActions.contains("read"));
permissions.setCanWrite(authorizedActions.contains("write"));
return entityFactory.createBucketEntity(dto, permissions);
})
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@ -2435,7 +2425,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
} }
@Override @Override
public RegistryEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO) { public RegistryClientEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO) {
final RevisionClaim revisionClaim = new StandardRevisionClaim(revision); final RevisionClaim revisionClaim = new StandardRevisionClaim(revision);
final NiFiUser user = NiFiUserUtils.getNiFiUser(); final NiFiUser user = NiFiUserUtils.getNiFiUser();
@ -2454,7 +2444,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}); });
final FlowRegistry updatedReg = revisionUpdate.getComponent(); final FlowRegistry updatedReg = revisionUpdate.getComponent();
return createRegistryEntity(updatedReg); return createRegistryClientEntity(updatedReg);
} }
@Override @Override
@ -2463,7 +2453,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
} }
@Override @Override
public RegistryEntity deleteRegistryClient(final Revision revision, final String registryId) { public RegistryClientEntity deleteRegistryClient(final Revision revision, final String registryId) {
final RevisionClaim claim = new StandardRevisionClaim(revision); final RevisionClaim claim = new StandardRevisionClaim(revision);
final NiFiUser user = NiFiUserUtils.getNiFiUser(); final NiFiUser user = NiFiUserUtils.getNiFiUser();
@ -2473,7 +2463,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
return reg; return reg;
}); });
return createRegistryEntity(registry); return createRegistryClientEntity(registry);
} }
@Override @Override
@ -3695,10 +3685,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
// add first snapshot to the flow in the registry // add first snapshot to the flow in the registry
registeredSnapshot = registerVersionedFlowSnapshot(registryId, registeredFlow, versionedProcessGroup, versionedFlowDto.getComments(), expectedVersion); registeredSnapshot = registerVersionedFlowSnapshot(registryId, registeredFlow, versionedProcessGroup, versionedFlowDto.getComments(), expectedVersion);
} catch (final NiFiRegistryException e) { } catch (final NiFiRegistryException e) {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e.getLocalizedMessage());
} catch (final IOException ioe) { } catch (final IOException ioe) {
// will result in a 500: Internal Server Error throw new IllegalStateException("Failed to communicate with Flow Registry when attempting to " + action);
throw new RuntimeException("Failed to communicate with Flow Registry when attempting to " + action);
} }
final Bucket bucket = registeredSnapshot.getBucket(); final Bucket bucket = registeredSnapshot.getBucket();
@ -4105,7 +4094,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(groupId); final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(groupId);
final RevisionUpdate<ProcessGroupDTO> snapshot = updateComponent(user, revision, final RevisionUpdate<ProcessGroupDTO> snapshot = updateComponent(user, revision,
processGroupNode, processGroupNode,
() -> processGroupDAO.updateProcessGroupFlow(groupId, proposedFlowSnapshot, versionControlInfo, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows), () -> processGroupDAO.updateProcessGroupFlow(groupId, user, proposedFlowSnapshot, versionControlInfo, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows),
processGroup -> dtoFactory.createProcessGroupDto(processGroup)); processGroup -> dtoFactory.createProcessGroupDto(processGroup));
final PermissionsDTO permissions = dtoFactory.createPermissionsDto(processGroupNode); final PermissionsDTO permissions = dtoFactory.createPermissionsDto(processGroupNode);

View File

@ -46,8 +46,8 @@ import org.apache.nifi.web.api.entity.ControllerServiceEntity;
import org.apache.nifi.web.api.entity.Entity; import org.apache.nifi.web.api.entity.Entity;
import org.apache.nifi.web.api.entity.HistoryEntity; import org.apache.nifi.web.api.entity.HistoryEntity;
import org.apache.nifi.web.api.entity.NodeEntity; import org.apache.nifi.web.api.entity.NodeEntity;
import org.apache.nifi.web.api.entity.RegistriesEntity; import org.apache.nifi.web.api.entity.RegistryClientsEntity;
import org.apache.nifi.web.api.entity.RegistryEntity; import org.apache.nifi.web.api.entity.RegistryClientEntity;
import org.apache.nifi.web.api.entity.ReportingTaskEntity; import org.apache.nifi.web.api.entity.ReportingTaskEntity;
import org.apache.nifi.web.api.request.ClientIdParameter; import org.apache.nifi.web.api.request.ClientIdParameter;
import org.apache.nifi.web.api.request.DateTimeParameter; import org.apache.nifi.web.api.request.DateTimeParameter;
@ -91,12 +91,12 @@ public class ControllerResource extends ApplicationResource {
/** /**
* Populate the uri's for the specified registry. * Populate the uri's for the specified registry.
* *
* @param registryEntity registry * @param registryClientEntity registry
* @return dtos * @return dtos
*/ */
public RegistryEntity populateRemainingRegistryEntityContent(final RegistryEntity registryEntity) { public RegistryClientEntity populateRemainingRegistryEntityContent(final RegistryClientEntity registryClientEntity) {
registryEntity.setUri(generateResourceUri("controller", "registry-clients", registryEntity.getId())); registryClientEntity.setUri(generateResourceUri("controller", "registry-clients", registryClientEntity.getId()));
return registryEntity; return registryClientEntity;
} }
/** /**
@ -316,7 +316,7 @@ public class ControllerResource extends ApplicationResource {
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Path("registry-clients") @Path("registry-clients")
@ApiOperation(value = "Gets the listing of available registry clients", response = RegistriesEntity.class, authorizations = { @ApiOperation(value = "Gets the listing of available registry clients", response = RegistryClientsEntity.class, authorizations = {
@Authorization(value = "Read - /flow") @Authorization(value = "Read - /flow")
}) })
@ApiResponses(value = { @ApiResponses(value = {
@ -333,10 +333,10 @@ public class ControllerResource extends ApplicationResource {
return replicate(HttpMethod.GET); return replicate(HttpMethod.GET);
} }
final Set<RegistryEntity> registries = serviceFacade.getRegistryClients(); final Set<RegistryClientEntity> registries = serviceFacade.getRegistryClients();
registries.forEach(registry -> populateRemainingRegistryEntityContent(registry)); registries.forEach(registry -> populateRemainingRegistryEntityContent(registry));
final RegistriesEntity registryEntities = new RegistriesEntity(); final RegistryClientsEntity registryEntities = new RegistryClientsEntity();
registryEntities.setRegistries(registries); registryEntities.setRegistries(registries);
return generateOkResponse(registryEntities).build(); return generateOkResponse(registryEntities).build();
@ -346,8 +346,8 @@ public class ControllerResource extends ApplicationResource {
* Creates a new Registry. * Creates a new Registry.
* *
* @param httpServletRequest request * @param httpServletRequest request
* @param requestRegistryEntity A registryEntity. * @param requestRegistryClientEntity A registryClientEntity.
* @return A registryEntity. * @return A registryClientEntity.
*/ */
@POST @POST
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@ -355,7 +355,7 @@ public class ControllerResource extends ApplicationResource {
@Path("registry-clients") @Path("registry-clients")
@ApiOperation( @ApiOperation(
value = "Creates a new registry client", value = "Creates a new registry client",
response = RegistryEntity.class, response = RegistryClientEntity.class,
authorizations = { authorizations = {
@Authorization(value = "Write - /controller") @Authorization(value = "Write - /controller")
} }
@ -373,28 +373,28 @@ public class ControllerResource extends ApplicationResource {
@ApiParam( @ApiParam(
value = "The registry configuration details.", value = "The registry configuration details.",
required = true required = true
) final RegistryEntity requestRegistryEntity) { ) final RegistryClientEntity requestRegistryClientEntity) {
if (requestRegistryEntity == null || requestRegistryEntity.getComponent() == null) { if (requestRegistryClientEntity == null || requestRegistryClientEntity.getComponent() == null) {
throw new IllegalArgumentException("Registry details must be specified."); throw new IllegalArgumentException("Registry details must be specified.");
} }
if (requestRegistryEntity.getRevision() == null || (requestRegistryEntity.getRevision().getVersion() == null || requestRegistryEntity.getRevision().getVersion() != 0)) { if (requestRegistryClientEntity.getRevision() == null || (requestRegistryClientEntity.getRevision().getVersion() == null || requestRegistryClientEntity.getRevision().getVersion() != 0)) {
throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Registry."); throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Registry.");
} }
final RegistryDTO requestReportingTask = requestRegistryEntity.getComponent(); final RegistryDTO requestReportingTask = requestRegistryClientEntity.getComponent();
if (requestReportingTask.getId() != null) { if (requestReportingTask.getId() != null) {
throw new IllegalArgumentException("Registry ID cannot be specified."); throw new IllegalArgumentException("Registry ID cannot be specified.");
} }
if (isReplicateRequest()) { if (isReplicateRequest()) {
return replicate(HttpMethod.POST, requestRegistryEntity); return replicate(HttpMethod.POST, requestRegistryClientEntity);
} }
return withWriteLock( return withWriteLock(
serviceFacade, serviceFacade,
requestRegistryEntity, requestRegistryClientEntity,
lookup -> { lookup -> {
authorizeController(RequestAction.WRITE); authorizeController(RequestAction.WRITE);
}, },
@ -407,7 +407,7 @@ public class ControllerResource extends ApplicationResource {
// create the reporting task and generate the json // create the reporting task and generate the json
final Revision revision = getRevision(registryEntity, registry.getId()); final Revision revision = getRevision(registryEntity, registry.getId());
final RegistryEntity entity = serviceFacade.createRegistryClient(revision, registry); final RegistryClientEntity entity = serviceFacade.createRegistryClient(revision, registry);
populateRemainingRegistryEntityContent(entity); populateRemainingRegistryEntityContent(entity);
// build the response // build the response
@ -420,7 +420,7 @@ public class ControllerResource extends ApplicationResource {
* Retrieves the specified registry. * Retrieves the specified registry.
* *
* @param id The id of the registry to retrieve * @param id The id of the registry to retrieve
* @return A registryEntity. * @return A registryClientEntity.
*/ */
@GET @GET
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
@ -428,7 +428,7 @@ public class ControllerResource extends ApplicationResource {
@Path("/registry-clients/{id}") @Path("/registry-clients/{id}")
@ApiOperation( @ApiOperation(
value = "Gets a registry client", value = "Gets a registry client",
response = RegistryEntity.class, response = RegistryClientEntity.class,
authorizations = { authorizations = {
@Authorization(value = "Read - /controller") @Authorization(value = "Read - /controller")
} }
@ -442,7 +442,7 @@ public class ControllerResource extends ApplicationResource {
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
} }
) )
public Response getRegistry( public Response getRegistryClient(
@ApiParam( @ApiParam(
value = "The registry id.", value = "The registry id.",
required = true required = true
@ -457,7 +457,7 @@ public class ControllerResource extends ApplicationResource {
authorizeController(RequestAction.READ); authorizeController(RequestAction.READ);
// get the registry // get the registry
final RegistryEntity entity = serviceFacade.getRegistryClient(id); final RegistryClientEntity entity = serviceFacade.getRegistryClient(id);
populateRemainingRegistryEntityContent(entity); populateRemainingRegistryEntityContent(entity);
return generateOkResponse(entity).build(); return generateOkResponse(entity).build();
@ -477,7 +477,7 @@ public class ControllerResource extends ApplicationResource {
@Path("/registry-clients/{id}") @Path("/registry-clients/{id}")
@ApiOperation( @ApiOperation(
value = "Updates a registry client", value = "Updates a registry client",
response = RegistryEntity.class, response = RegistryClientEntity.class,
authorizations = { authorizations = {
@Authorization(value = "Write - /controller") @Authorization(value = "Write - /controller")
} }
@ -501,7 +501,7 @@ public class ControllerResource extends ApplicationResource {
@ApiParam( @ApiParam(
value = "The registry configuration details.", value = "The registry configuration details.",
required = true required = true
) final RegistryEntity requestRegsitryEntity) { ) final RegistryClientEntity requestRegsitryEntity) {
if (requestRegsitryEntity == null || requestRegsitryEntity.getComponent() == null) { if (requestRegsitryEntity == null || requestRegsitryEntity.getComponent() == null) {
throw new IllegalArgumentException("Registry details must be specified."); throw new IllegalArgumentException("Registry details must be specified.");
@ -536,7 +536,7 @@ public class ControllerResource extends ApplicationResource {
final RegistryDTO registry = registryEntity.getComponent(); final RegistryDTO registry = registryEntity.getComponent();
// update the controller service // update the controller service
final RegistryEntity entity = serviceFacade.updateRegistryClient(revision, registry); final RegistryClientEntity entity = serviceFacade.updateRegistryClient(revision, registry);
populateRemainingRegistryEntityContent(entity); populateRemainingRegistryEntityContent(entity);
return generateOkResponse(entity).build(); return generateOkResponse(entity).build();
@ -562,7 +562,7 @@ public class ControllerResource extends ApplicationResource {
@Path("/registry-clients/{id}") @Path("/registry-clients/{id}")
@ApiOperation( @ApiOperation(
value = "Deletes a registry client", value = "Deletes a registry client",
response = RegistryEntity.class, response = RegistryClientEntity.class,
authorizations = { authorizations = {
@Authorization(value = "Write - /controller") @Authorization(value = "Write - /controller")
} }
@ -598,14 +598,14 @@ public class ControllerResource extends ApplicationResource {
return replicate(HttpMethod.DELETE); return replicate(HttpMethod.DELETE);
} }
final RegistryEntity requestRegistryEntity = new RegistryEntity(); final RegistryClientEntity requestRegistryClientEntity = new RegistryClientEntity();
requestRegistryEntity.setId(id); requestRegistryClientEntity.setId(id);
// handle expects request (usually from the cluster manager) // handle expects request (usually from the cluster manager)
final Revision requestRevision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id); final Revision requestRevision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
return withWriteLock( return withWriteLock(
serviceFacade, serviceFacade,
requestRegistryEntity, requestRegistryClientEntity,
requestRevision, requestRevision,
lookup -> { lookup -> {
authorizeController(RequestAction.WRITE); authorizeController(RequestAction.WRITE);
@ -613,7 +613,7 @@ public class ControllerResource extends ApplicationResource {
() -> serviceFacade.verifyDeleteRegistry(id), () -> serviceFacade.verifyDeleteRegistry(id),
(revision, registryEntity) -> { (revision, registryEntity) -> {
// delete the specified registry // delete the specified registry
final RegistryEntity entity = serviceFacade.deleteRegistryClient(revision, registryEntity.getId()); final RegistryClientEntity entity = serviceFacade.deleteRegistryClient(revision, registryEntity.getId());
return generateOkResponse(entity).build(); return generateOkResponse(entity).build();
} }
); );

View File

@ -88,6 +88,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusEntity; import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
import org.apache.nifi.web.api.entity.ProcessorTypesEntity; import org.apache.nifi.web.api.entity.ProcessorTypesEntity;
import org.apache.nifi.web.api.entity.RegistriesEntity; import org.apache.nifi.web.api.entity.RegistriesEntity;
import org.apache.nifi.web.api.entity.RegistryClientsEntity;
import org.apache.nifi.web.api.entity.RegistryEntity; import org.apache.nifi.web.api.entity.RegistryEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ReportingTaskEntity; import org.apache.nifi.web.api.entity.ReportingTaskEntity;
@ -1316,7 +1317,7 @@ public class FlowResource extends ApplicationResource {
@Consumes(MediaType.WILDCARD) @Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Path("registries") @Path("registries")
@ApiOperation(value = "Gets the listing of available registries", response = RegistriesEntity.class, authorizations = { @ApiOperation(value = "Gets the listing of available registries", response = RegistryClientsEntity.class, authorizations = {
@Authorization(value = "Read - /flow") @Authorization(value = "Read - /flow")
}) })
@ApiResponses(value = { @ApiResponses(value = {

View File

@ -183,7 +183,7 @@ public class VersionsResource extends ApplicationResource {
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
}) })
public Response createVersionControlRequest( public Response createVersionControlRequest(
@ApiParam(value = "The versioned flow details.", required = true) final CreateActiveRequestEntity requestEntity) throws InterruptedException { @ApiParam(value = "The versioned flow details.", required = true) final CreateActiveRequestEntity requestEntity) {
if (isReplicateRequest()) { if (isReplicateRequest()) {
return replicate(HttpMethod.POST); return replicate(HttpMethod.POST);
@ -412,7 +412,7 @@ public class VersionsResource extends ApplicationResource {
}) })
public Response saveToFlowRegistry( public Response saveToFlowRegistry(
@ApiParam("The process group id.") @PathParam("id") final String groupId, @ApiParam("The process group id.") @PathParam("id") final String groupId,
@ApiParam(value = "The versioned flow details.", required = true) final StartVersionControlRequestEntity requestEntity) throws IOException { @ApiParam(value = "The versioned flow details.", required = true) final StartVersionControlRequestEntity requestEntity) {
// Verify the request // Verify the request
final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision(); final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();
@ -569,8 +569,9 @@ public class VersionsResource extends ApplicationResource {
return requestId; return requestId;
} }
private void replicateVersionControlMapping(final VersionControlComponentMappingEntity mappingEntity, final StartVersionControlRequestEntity requestEntity, final URI requestUri, private void replicateVersionControlMapping(final VersionControlComponentMappingEntity mappingEntity, final StartVersionControlRequestEntity requestEntity,
final String groupId) { final URI requestUri, final String groupId) {
final Map<String, String> headers = new HashMap<>(); final Map<String, String> headers = new HashMap<>();
headers.put("content-type", MediaType.APPLICATION_JSON); headers.put("content-type", MediaType.APPLICATION_JSON);
@ -652,7 +653,7 @@ public class VersionsResource extends ApplicationResource {
value = "If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response.", value = "If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response.",
required = false) required = false)
@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId, @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
@ApiParam("The process group id.") @PathParam("id") final String groupId) throws IOException { @ApiParam("The process group id.") @PathParam("id") final String groupId) {
if (isReplicateRequest()) { if (isReplicateRequest()) {
return replicate(HttpMethod.DELETE); return replicate(HttpMethod.DELETE);
@ -705,7 +706,7 @@ public class VersionsResource extends ApplicationResource {
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
}) })
public Response updateFlowVersion(@ApiParam("The process group id.") @PathParam("id") final String groupId, public Response updateFlowVersion(@ApiParam("The process group id.") @PathParam("id") final String groupId,
@ApiParam(value = "The controller service configuration details.", required = true) final VersionedFlowSnapshotEntity requestEntity) throws IOException, LifecycleManagementException { @ApiParam(value = "The controller service configuration details.", required = true) final VersionedFlowSnapshotEntity requestEntity) {
// Verify the request // Verify the request
final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision(); final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();

View File

@ -272,10 +272,10 @@ public final class DtoFactory {
actionDto.setId(action.getId()); actionDto.setId(action.getId());
actionDto.setSourceId(action.getSourceId()); actionDto.setSourceId(action.getSourceId());
actionDto.setSourceName(action.getSourceName()); actionDto.setSourceName(action.getSourceName());
actionDto.setSourceType(action.getSourceType().name()); actionDto.setSourceType(action.getSourceType().toString());
actionDto.setTimestamp(action.getTimestamp()); actionDto.setTimestamp(action.getTimestamp());
actionDto.setUserIdentity(action.getUserIdentity()); actionDto.setUserIdentity(action.getUserIdentity());
actionDto.setOperation(action.getOperation().name()); actionDto.setOperation(action.getOperation().toString());
actionDto.setActionDetails(createActionDetailsDto(action.getActionDetails())); actionDto.setActionDetails(createActionDetailsDto(action.getActionDetails()));
actionDto.setComponentDetails(createComponentDetailsDto(action.getComponentDetails())); actionDto.setComponentDetails(createComponentDetailsDto(action.getComponentDetails()));

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.ActionEntity;
import org.apache.nifi.web.api.entity.AffectedComponentEntity; import org.apache.nifi.web.api.entity.AffectedComponentEntity;
import org.apache.nifi.web.api.entity.AllowableValueEntity; import org.apache.nifi.web.api.entity.AllowableValueEntity;
import org.apache.nifi.web.api.entity.BucketEntity;
import org.apache.nifi.web.api.entity.BulletinEntity; import org.apache.nifi.web.api.entity.BulletinEntity;
import org.apache.nifi.web.api.entity.ComponentReferenceEntity; import org.apache.nifi.web.api.entity.ComponentReferenceEntity;
import org.apache.nifi.web.api.entity.ConnectionEntity; import org.apache.nifi.web.api.entity.ConnectionEntity;
@ -56,6 +57,8 @@ import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity; import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusEntity; import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusSnapshotEntity; import org.apache.nifi.web.api.entity.ProcessorStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.RegistryClientEntity;
import org.apache.nifi.web.api.entity.RegistryEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity; import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
@ -546,4 +549,43 @@ public final class EntityFactory {
entity.setProcessGroupRevision(processGroupRevision); entity.setProcessGroupRevision(processGroupRevision);
return entity; return entity;
} }
public RegistryClientEntity createRegistryClientEntity(final RegistryDTO dto, final RevisionDTO revision, final PermissionsDTO permissions) {
final RegistryClientEntity entity = new RegistryClientEntity();
entity.setRevision(revision);
entity.setPermissions(permissions);
if (dto != null) {
entity.setId(dto.getId());
if (permissions != null && permissions.getCanRead()) {
entity.setComponent(dto);
}
}
return entity;
}
public RegistryEntity createRegistryEntity(final RegistryDTO dto) {
final RegistryEntity entity = new RegistryEntity();
if (dto != null) {
entity.setRegistry(dto);
}
return entity;
}
public BucketEntity createBucketEntity(final BucketDTO dto, final PermissionsDTO permissions) {
final BucketEntity entity = new BucketEntity();
entity.setId(dto.getId());
entity.setPermissions(permissions);
if (permissions != null && permissions.getCanRead()) {
entity.setBucket(dto);
}
return entity;
}
} }

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.nifi.web.dao; package org.apache.nifi.web.dao;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.controller.ScheduledState; import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.service.ControllerServiceState; import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.ProcessGroup;
@ -118,7 +119,7 @@ public interface ProcessGroupDAO {
* update the contents of that Process Group * update the contents of that Process Group
* @return the process group * @return the process group
*/ */
ProcessGroup updateProcessGroupFlow(String groupId, VersionedFlowSnapshot proposedSnapshot, VersionControlInformationDTO versionControlInformation, String componentIdSeed, ProcessGroup updateProcessGroupFlow(String groupId, NiFiUser user, VersionedFlowSnapshot proposedSnapshot, VersionControlInformationDTO versionControlInformation, String componentIdSeed,
boolean verifyNotModified, boolean updateSettings, boolean updateDescendantVersionedFlows); boolean verifyNotModified, boolean updateSettings, boolean updateDescendantVersionedFlows);
/** /**
@ -141,10 +142,11 @@ public interface ProcessGroupDAO {
/** /**
* Updates the specified variable registry * Updates the specified variable registry
* *
* @param user the user performing the update
* @param variableRegistry the Variable Registry * @param variableRegistry the Variable Registry
* @return the Process Group that was updated * @return the Process Group that was updated
*/ */
ProcessGroup updateVariableRegistry(VariableRegistryDTO variableRegistry); ProcessGroup updateVariableRegistry(NiFiUser user, VariableRegistryDTO variableRegistry);
/** /**
* Verifies that the specified updates to a current Process Group can be applied at this time * Verifies that the specified updates to a current Process Group can be applied at this time

View File

@ -17,11 +17,6 @@
package org.apache.nifi.web.dao.impl; package org.apache.nifi.web.dao.impl;
import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import org.apache.nifi.authorization.user.NiFiUser; import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.registry.bucket.Bucket; import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.client.NiFiRegistryException; import org.apache.nifi.registry.client.NiFiRegistryException;
@ -36,6 +31,7 @@ import org.apache.nifi.web.dao.RegistryDAO;
import java.io.IOException; import java.io.IOException;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class FlowRegistryDAO implements RegistryDAO { public class FlowRegistryDAO implements RegistryDAO {
@ -65,7 +61,6 @@ public class FlowRegistryDAO implements RegistryDAO {
@Override @Override
public Set<FlowRegistry> getFlowRegistriesForUser(final NiFiUser user) { public Set<FlowRegistry> getFlowRegistriesForUser(final NiFiUser user) {
// TODO - implement to be user specific
return getFlowRegistries(); return getFlowRegistries();
} }

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.nifi.web.dao.impl; package org.apache.nifi.web.dao.impl;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.connectable.Connectable; import org.apache.nifi.connectable.Connectable;
import org.apache.nifi.connectable.Port; import org.apache.nifi.connectable.Port;
import org.apache.nifi.connectable.Position; import org.apache.nifi.connectable.Position;
@ -143,7 +144,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
} }
@Override @Override
public CompletableFuture<Void> scheduleComponents(final String groupId, final ScheduledState state, final Set<String> componentIds) { public Future<Void> scheduleComponents(final String groupId, final ScheduledState state, final Set<String> componentIds) {
final ProcessGroup group = locateProcessGroup(flowController, groupId); final ProcessGroup group = locateProcessGroup(flowController, groupId);
CompletableFuture<Void> future = CompletableFuture.completedFuture(null); CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
@ -275,8 +276,9 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
} }
@Override @Override
public ProcessGroup updateProcessGroupFlow(final String groupId, final VersionedFlowSnapshot proposedSnapshot, final VersionControlInformationDTO versionControlInformation, public ProcessGroup updateProcessGroupFlow(final String groupId, final NiFiUser user, final VersionedFlowSnapshot proposedSnapshot, final VersionControlInformationDTO versionControlInformation,
final String componentIdSeed, final boolean verifyNotModified, final boolean updateSettings, final boolean updateDescendantVersionedFlows) { final String componentIdSeed, final boolean verifyNotModified, final boolean updateSettings, final boolean updateDescendantVersionedFlows) {
final ProcessGroup group = locateProcessGroup(flowController, groupId); final ProcessGroup group = locateProcessGroup(flowController, groupId);
group.updateFlow(proposedSnapshot, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows); group.updateFlow(proposedSnapshot, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows);
@ -291,7 +293,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
} }
@Override @Override
public ProcessGroup updateVariableRegistry(final VariableRegistryDTO variableRegistry) { public ProcessGroup updateVariableRegistry(final NiFiUser user, final VariableRegistryDTO variableRegistry) {
final ProcessGroup group = locateProcessGroup(flowController, variableRegistry.getProcessGroupId()); final ProcessGroup group = locateProcessGroup(flowController, variableRegistry.getProcessGroupId());
if (group == null) { if (group == null) {
throw new ResourceNotFoundException("Could not find Process Group with ID " + variableRegistry.getProcessGroupId()); throw new ResourceNotFoundException("Could not find Process Group with ID " + variableRegistry.getProcessGroupId());

View File

@ -80,6 +80,7 @@
</div> </div>
</div> </div>
</div> </div>
<div id="variable-message">Variables do not support sensitive values and will be included when versioning a Process Group.</div>
</div> </div>
<div id="new-variable-dialog" class="dialog cancellable small-dialog hidden"> <div id="new-variable-dialog" class="dialog cancellable small-dialog hidden">
<div class="dialog-content"> <div class="dialog-content">

View File

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--%> --%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %> <%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="nf-ok-dialog" class="hidden small-dialog"> <div id="nf-ok-dialog" class="hidden medium-short-dialog">
<div class="dialog-content"> <div class="dialog-content">
<div id="nf-ok-dialog-content"></div> <div id="nf-ok-dialog-content"></div>
</div> </div>

View File

@ -323,6 +323,13 @@ div.slick-cell div.overridden {
text-decoration: line-through; text-decoration: line-through;
} }
#variable-message {
position: absolute;
top: 550px;
left: 20px;
font-size: 13px;
}
/* /*
Registry configuration dialog Registry configuration dialog
*/ */

View File

@ -43,6 +43,15 @@
min-width: 470px; min-width: 470px;
} }
.medium-short-dialog {
max-height: 32%;
max-width: 34%;
min-height: 250px;
min-width: 440px;
font-size: 13px;
line-height: 1.3;
}
.large-dialog { .large-dialog {
max-height: 72%; max-height: 72%;
max-width: 55%; max-width: 55%;

View File

@ -920,7 +920,7 @@
'delete': function (selection) { 'delete': function (selection) {
if (nfCommon.isUndefined(selection) || selection.empty()) { if (nfCommon.isUndefined(selection) || selection.empty()) {
nfDialog.showOkDialog({ nfDialog.showOkDialog({
headerText: 'Reload', headerText: 'Delete Components',
dialogContent: 'No eligible components are selected. Please select the components to be deleted.' dialogContent: 'No eligible components are selected. Please select the components to be deleted.'
}); });
} else { } else {

View File

@ -180,9 +180,11 @@
* @param registryCombo * @param registryCombo
* @param bucketCombo * @param bucketCombo
* @param flowCombo * @param flowCombo
* @param selectBucket
* @param bucketCheck
* @returns {deferred} * @returns {deferred}
*/ */
var loadRegistries = function (dialog, registryCombo, bucketCombo, flowCombo, selectBucket) { var loadRegistries = function (dialog, registryCombo, bucketCombo, flowCombo, selectBucket, bucketCheck) {
return $.ajax({ return $.ajax({
type: 'GET', type: 'GET',
url: '../nifi-api/flow/registries', url: '../nifi-api/flow/registries',
@ -192,11 +194,11 @@
if (nfCommon.isDefinedAndNotNull(registriesResponse.registries) && registriesResponse.registries.length > 0) { if (nfCommon.isDefinedAndNotNull(registriesResponse.registries) && registriesResponse.registries.length > 0) {
registriesResponse.registries.sort(function (a, b) { registriesResponse.registries.sort(function (a, b) {
return a.component.name > b.component.name; return a.registry.name > b.registry.name;
}); });
$.each(registriesResponse.registries, function (_, registryEntity) { $.each(registriesResponse.registries, function (_, registryEntity) {
var registry = registryEntity.component; var registry = registryEntity.registry;
registries.push({ registries.push({
text: registry.name, text: registry.name,
value: registry.id, value: registry.id,
@ -216,7 +218,7 @@
registryCombo.combo({ registryCombo.combo({
options: registries, options: registries,
select: function (selectedOption) { select: function (selectedOption) {
selectRegistry(dialog, selectedOption, bucketCombo, flowCombo, selectBucket) selectRegistry(dialog, selectedOption, bucketCombo, flowCombo, selectBucket, bucketCheck)
} }
}); });
}).fail(nfErrorHandler.handleAjaxError); }).fail(nfErrorHandler.handleAjaxError);
@ -229,9 +231,10 @@
* @param bucketCombo * @param bucketCombo
* @param flowCombo * @param flowCombo
* @param selectBucket * @param selectBucket
* @param bucketCheck
* @returns {*} * @returns {*}
*/ */
var loadBuckets = function (registryIdentifier, bucketCombo, flowCombo, selectBucket) { var loadBuckets = function (registryIdentifier, bucketCombo, flowCombo, selectBucket, bucketCheck) {
return $.ajax({ return $.ajax({
type: 'GET', type: 'GET',
url: '../nifi-api/flow/registries/' + encodeURIComponent(registryIdentifier) + '/buckets', url: '../nifi-api/flow/registries/' + encodeURIComponent(registryIdentifier) + '/buckets',
@ -241,18 +244,33 @@
if (nfCommon.isDefinedAndNotNull(response.buckets) && response.buckets.length > 0) { if (nfCommon.isDefinedAndNotNull(response.buckets) && response.buckets.length > 0) {
response.buckets.sort(function (a, b) { response.buckets.sort(function (a, b) {
if (a.permissions.canRead === false && b.permissions.canRead === false) {
return 0;
} else if (a.permissions.canRead === false) {
return -1;
} else if (b.permissions.canRead === false) {
return 1;
}
return a.bucket.name > b.bucket.name; return a.bucket.name > b.bucket.name;
}); });
$.each(response.buckets, function (_, bucketEntity) { $.each(response.buckets, function (_, bucketEntity) {
if (bucketEntity.permissions.canRead === true) {
var bucket = bucketEntity.bucket; var bucket = bucketEntity.bucket;
if (bucketCheck(bucketEntity)) {
buckets.push({ buckets.push({
text: bucket.name, text: bucket.name,
value: bucket.id, value: bucket.id,
description: nfCommon.escapeHtml(bucket.description) description: nfCommon.escapeHtml(bucket.description)
}); });
}
}
}); });
} else { }
if (buckets.length === 0) {
buckets.push({ buckets.push({
text: 'No available buckets', text: 'No available buckets',
value: null, value: null,
@ -285,8 +303,9 @@
* @param bucketCombo * @param bucketCombo
* @param flowCombo * @param flowCombo
* @param selectBucket * @param selectBucket
* @param bucketCheck
*/ */
var selectRegistry = function (dialog, selectedOption, bucketCombo, flowCombo, selectBucket) { var selectRegistry = function (dialog, selectedOption, bucketCombo, flowCombo, selectBucket, bucketCheck) {
var showNoBucketsAvailable = function () { var showNoBucketsAvailable = function () {
bucketCombo.combo('destroy').combo({ bucketCombo.combo('destroy').combo({
options: [{ options: [{
@ -333,7 +352,7 @@
clearFlowVersionsGrid(); clearFlowVersionsGrid();
} }
loadBuckets(selectedOption.value, bucketCombo, flowCombo, selectBucket).fail(function () { loadBuckets(selectedOption.value, bucketCombo, flowCombo, selectBucket, bucketCheck).fail(function () {
showNoBucketsAvailable(); showNoBucketsAvailable();
}); });
} }
@ -744,7 +763,9 @@
}] }]
}).show(); }).show();
loadRegistries($('#import-flow-version-dialog'), registryCombo, bucketCombo, flowCombo, selectBucketImportVersion).done(function () { loadRegistries($('#import-flow-version-dialog'), registryCombo, bucketCombo, flowCombo, selectBucketImportVersion, function (bucketEntity) {
return true;
}).done(function () {
// show the import dialog // show the import dialog
$('#import-flow-version-dialog').modal('setHeaderText', 'Import Version').modal('setButtonModel', [{ $('#import-flow-version-dialog').modal('setHeaderText', 'Import Version').modal('setButtonModel', [{
buttonText: 'Import', buttonText: 'Import',
@ -904,6 +925,10 @@
* @param selectedBucket * @param selectedBucket
*/ */
var selectBucketImportVersion = function (selectedBucket) { var selectBucketImportVersion = function (selectedBucket) {
// clear the flow versions grid
clearFlowVersionsGrid();
if (nfCommon.isDefinedAndNotNull(selectedBucket.value)) {
// mark the flows as loading // mark the flows as loading
$('#import-flow-version-name-combo').combo('destroy').combo({ $('#import-flow-version-name-combo').combo('destroy').combo({
options: [{ options: [{
@ -914,13 +939,21 @@
}] }]
}); });
// clear the flow versions grid
clearFlowVersionsGrid();
var selectedRegistry = $('#import-flow-version-registry-combo').combo('getSelectedOption'); var selectedRegistry = $('#import-flow-version-registry-combo').combo('getSelectedOption');
// load the flows for the currently selected registry and bucket // load the flows for the currently selected registry and bucket
loadFlows(selectedRegistry.value, selectedBucket.value, selectVersionedFlow); loadFlows(selectedRegistry.value, selectedBucket.value, selectVersionedFlow);
} else {
// mark no flows available
$('#import-flow-version-name-combo').combo('destroy').combo({
options: [{
text: 'No available flows',
value: null,
optionClass: 'unset',
disabled: true
}]
});
}
}; };
/** /**
@ -988,7 +1021,22 @@
var importFlowVersionGrid = $('#import-flow-version-table').data('gridInstance'); var importFlowVersionGrid = $('#import-flow-version-table').data('gridInstance');
if (nfCommon.isDefinedAndNotNull(importFlowVersionGrid)) { if (nfCommon.isDefinedAndNotNull(importFlowVersionGrid)) {
var selected = importFlowVersionGrid.getSelectedRows(); var selected = importFlowVersionGrid.getSelectedRows();
// if the version label is visible, this is a change version request so disable when
// the version that represents the current version is selected
if ($('#import-flow-version-label').is(':visible')) {
if (selected.length === 1) {
var selectedFlow = importFlowVersionGrid.getDataItem(selected[0]);
var currentVersion = parseInt($('#import-flow-version-label').text(), 10);
return currentVersion === selectedFlow.version;
} else {
return true;
}
} else {
// if importing, enable when a single row is selecting
return selected.length !== 1; return selected.length !== 1;
}
} else { } else {
return true; return true;
} }
@ -1731,7 +1779,9 @@
// reposition the version label // reposition the version label
$('#save-flow-version-label').css('margin-top', '0'); $('#save-flow-version-label').css('margin-top', '0');
loadRegistries($('#save-flow-version-dialog'), registryCombo, bucketCombo, null, selectBucketSaveFlowVersion).done(function () { loadRegistries($('#save-flow-version-dialog'), registryCombo, bucketCombo, null, selectBucketSaveFlowVersion, function (bucketEntity) {
return bucketEntity.permissions.canWrite === true;
}).done(function () {
deferred.resolve(); deferred.resolve();
}).fail(function () { }).fail(function () {
deferred.reject(); deferred.reject();

View File

@ -1095,6 +1095,7 @@
// up to date current // up to date current
var upToDate = details.select('text.process-group-up-to-date') var upToDate = details.select('text.process-group-up-to-date')
.style('visibility', 'visible')
.classed('up-to-date', function (d) { .classed('up-to-date', function (d) {
return d.component.upToDateCount > 0; return d.component.upToDateCount > 0;
}) })
@ -1102,6 +1103,7 @@
return d.component.upToDateCount === 0; return d.component.upToDateCount === 0;
}); });
var upToDateCount = details.select('text.process-group-up-to-date-count') var upToDateCount = details.select('text.process-group-up-to-date-count')
.style('visibility', 'visible')
.attr('x', function () { .attr('x', function () {
var updateToDateCountX = parseInt(upToDate.attr('x'), 10); var updateToDateCountX = parseInt(upToDate.attr('x'), 10);
return updateToDateCountX + Math.round(upToDate.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER; return updateToDateCountX + Math.round(upToDate.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER;
@ -1112,6 +1114,7 @@
// update locally modified // update locally modified
var locallyModified = details.select('text.process-group-locally-modified') var locallyModified = details.select('text.process-group-locally-modified')
.style('visibility', 'visible')
.classed('locally-modified', function (d) { .classed('locally-modified', function (d) {
return d.component.locallyModifiedCount > 0; return d.component.locallyModifiedCount > 0;
}) })
@ -1123,6 +1126,7 @@
return upToDateX + Math.round(upToDateCount.node().getComputedTextLength()) + CONTENTS_SPACER; return upToDateX + Math.round(upToDateCount.node().getComputedTextLength()) + CONTENTS_SPACER;
}); });
var locallyModifiedCount = details.select('text.process-group-locally-modified-count') var locallyModifiedCount = details.select('text.process-group-locally-modified-count')
.style('visibility', 'visible')
.attr('x', function () { .attr('x', function () {
var locallyModifiedCountX = parseInt(locallyModified.attr('x'), 10); var locallyModifiedCountX = parseInt(locallyModified.attr('x'), 10);
return locallyModifiedCountX + Math.round(locallyModified.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER; return locallyModifiedCountX + Math.round(locallyModified.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER;
@ -1133,6 +1137,7 @@
// update stale // update stale
var stale = details.select('text.process-group-stale') var stale = details.select('text.process-group-stale')
.style('visibility', 'visible')
.classed('stale', function (d) { .classed('stale', function (d) {
return d.component.staleCount > 0; return d.component.staleCount > 0;
}) })
@ -1144,6 +1149,7 @@
return locallyModifiedX + Math.round(locallyModifiedCount.node().getComputedTextLength()) + CONTENTS_SPACER; return locallyModifiedX + Math.round(locallyModifiedCount.node().getComputedTextLength()) + CONTENTS_SPACER;
}); });
var staleCount = details.select('text.process-group-stale-count') var staleCount = details.select('text.process-group-stale-count')
.style('visibility', 'visible')
.attr('x', function () { .attr('x', function () {
var staleCountX = parseInt(stale.attr('x'), 10); var staleCountX = parseInt(stale.attr('x'), 10);
return staleCountX + Math.round(stale.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER; return staleCountX + Math.round(stale.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER;
@ -1154,6 +1160,7 @@
// update locally modified and stale // update locally modified and stale
var locallyModifiedAndStale = details.select('text.process-group-locally-modified-and-stale') var locallyModifiedAndStale = details.select('text.process-group-locally-modified-and-stale')
.style('visibility', 'visible')
.classed('locally-modified-and-stale', function (d) { .classed('locally-modified-and-stale', function (d) {
return d.component.locallyModifiedAndStaleCount > 0; return d.component.locallyModifiedAndStaleCount > 0;
}) })
@ -1165,6 +1172,7 @@
return staleX + Math.round(staleCount.node().getComputedTextLength()) + CONTENTS_SPACER; return staleX + Math.round(staleCount.node().getComputedTextLength()) + CONTENTS_SPACER;
}); });
var locallyModifiedAndStaleCount = details.select('text.process-group-locally-modified-and-stale-count') var locallyModifiedAndStaleCount = details.select('text.process-group-locally-modified-and-stale-count')
.style('visibility', 'visible')
.attr('x', function () { .attr('x', function () {
var locallyModifiedAndStaleCountX = parseInt(locallyModifiedAndStale.attr('x'), 10); var locallyModifiedAndStaleCountX = parseInt(locallyModifiedAndStale.attr('x'), 10);
return locallyModifiedAndStaleCountX + Math.round(locallyModifiedAndStale.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER; return locallyModifiedAndStaleCountX + Math.round(locallyModifiedAndStale.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER;
@ -1175,6 +1183,7 @@
// update sync failure // update sync failure
var syncFailure = details.select('text.process-group-sync-failure') var syncFailure = details.select('text.process-group-sync-failure')
.style('visibility', 'visible')
.classed('sync-failure', function (d) { .classed('sync-failure', function (d) {
return d.component.syncFailureCount > 0; return d.component.syncFailureCount > 0;
}) })
@ -1186,6 +1195,7 @@
return syncFailureX + Math.round(locallyModifiedAndStaleCount.node().getComputedTextLength()) + CONTENTS_SPACER - 2; return syncFailureX + Math.round(locallyModifiedAndStaleCount.node().getComputedTextLength()) + CONTENTS_SPACER - 2;
}); });
details.select('text.process-group-sync-failure-count') details.select('text.process-group-sync-failure-count')
.style('visibility', 'visible')
.attr('x', function () { .attr('x', function () {
var syncFailureCountX = parseInt(syncFailure.attr('x'), 10); var syncFailureCountX = parseInt(syncFailure.attr('x'), 10);
return syncFailureCountX + Math.round(syncFailure.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER; return syncFailureCountX + Math.round(syncFailure.node().getComputedTextLength()) + CONTENTS_VALUE_SPACER;
@ -1195,20 +1205,22 @@
}); });
} else { } else {
// update version control information // update version control information
processGroup.select('text.version-control').style('visibility', false).text(''); processGroup.select('text.version-control').style('visibility', 'hidden');
// clear the process group comments // clear the process group comments
processGroup.select('path.component-comments').style('visibility', false); processGroup.select('path.component-comments').style('visibility', 'hidden');
// clear the encapsulate versioned pg counts // clear the encapsulate versioned pg counts
details.select('text.process-group-up-to-date').style('visibility', false); details.select('text.process-group-up-to-date').style('visibility', 'hidden');
details.select('text.process-group-up-to-date-count').style('visibility', false); details.select('text.process-group-up-to-date-count').style('visibility', 'hidden');
details.select('text.process-group-locally-modified').style('visibility', false); details.select('text.process-group-locally-modified').style('visibility', 'hidden');
details.select('text.process-group-locally-modified-count').style('visibility', false); details.select('text.process-group-locally-modified-count').style('visibility', 'hidden');
details.select('text.process-group-stale').style('visibility', false); details.select('text.process-group-stale').style('visibility', 'hidden');
details.select('text.process-group-stale-count').style('visibility', false); details.select('text.process-group-stale-count').style('visibility', 'hidden');
details.select('text.process-group-locally-modified-and-stale').style('visibility', false); details.select('text.process-group-locally-modified-and-stale').style('visibility', 'hidden');
details.select('text.process-group-locally-modified-and-stale-count').style('visibility', false); details.select('text.process-group-locally-modified-and-stale-count').style('visibility', 'hidden');
details.select('text.process-group-sync-failure').style('visibility', 'hidden');
details.select('text.process-group-sync-failure-count').style('visibility', 'hidden');
// clear the process group name // clear the process group name
processGroup.select('text.process-group-name') processGroup.select('text.process-group-name')