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 {
Add,
Remove,
Paste,
Configure,
Move,
Disconnect,
Connect,
Start,
Stop,
Enable,
Disable,
Batch,
Purge,
ClearState;
Add("Add"),
Remove("Remove"),
Paste("Paste"),
Configure("Configure"),
Move("Move"),
Disconnect("Disconnect"),
Connect("Connect"),
Start("Start"),
Stop("Stop"),
Enable("Enable"),
Disable("Disable"),
Batch("Batch"),
Purge("Purge"),
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(2, action.getSourceId());
statement.setString(3, StringUtils.left(action.getSourceName(), 1000));
statement.setString(4, action.getSourceType().toString());
statement.setString(5, action.getOperation().toString());
statement.setString(4, action.getSourceType().name());
statement.setString(5, action.getOperation().name());
statement.setTimestamp(6, new java.sql.Timestamp(action.getTimestamp().getTime()));
// insert the action

View File

@ -17,6 +17,7 @@
package org.apache.nifi.web.api.entity;
import org.apache.nifi.web.api.dto.BucketDTO;
import org.apache.nifi.web.api.dto.PermissionsDTO;
import javax.xml.bind.annotation.XmlRootElement;
@ -26,8 +27,17 @@ import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "bucketEntity")
public class BucketEntity extends Entity {
private String id;
private BucketDTO bucket;
private PermissionsDTO permissions;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public BucketDTO getBucket() {
return bucket;
@ -36,4 +46,12 @@ public class BucketEntity extends Entity {
public void setBucket(BucketDTO 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.
*/
@XmlRootElement(name = "registriesEntity")
@XmlRootElement(name = "registryClientsEntity")
public class RegistriesEntity extends Entity {
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() {
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.
*/
@XmlRootElement(name = "registryEntity")
public class RegistryEntity extends ComponentEntity {
public class RegistryEntity {
private RegistryDTO component;
private RegistryDTO registry;
public RegistryDTO getComponent() {
return component;
public RegistryDTO getRegistry() {
return registry;
}
public void setComponent(RegistryDTO component) {
this.component = component;
public void setRegistry(RegistryDTO registry) {
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.service.ControllerServiceState;
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.VariableRegistryDTO;
import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
import org.apache.nifi.web.dao.ProcessGroupDAO;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@ -39,6 +42,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.concurrent.Future;
/**
* Audits process group creation/removal and configuration changes.
@ -173,10 +177,13 @@ public class ProcessGroupAuditor extends NiFiAuditor {
* @throws Throwable ex
*/
@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)")
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 Future<Void> result = (Future<Void>) proceedingJoinPoint.proceed();
// determine the running state
if (ScheduledState.RUNNING.equals(state)) {
operation = Operation.Start;
@ -184,7 +191,9 @@ public class ProcessGroupAuditor extends NiFiAuditor {
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 groupId group id
* @param state controller serivce state state
* @param state controller service state
* @throws Throwable ex
*/
@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)")
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
final Operation operation;
if (ControllerServiceState.ENABLED.equals(state)) {
operation = Operation.Enable;
} else {
operation = Operation.Disable;
}
saveUpdateAction(proceedingJoinPoint, groupId, operation);
saveUpdateAction(NiFiUserUtils.getNiFiUser(), groupId, operation);
return result;
}
/**
* Audits the update of process group variable registry.
*
* @param proceedingJoinPoint join point
* @param groupId group id
* @param user the user performing the action
* @param variableRegistry variable registry
* @throws Throwable ex
*/
@Around("within(org.apache.nifi.web.dao.ProcessGroupDAO+) && "
+ "execution(org.apache.nifi.groups.ProcessGroup updateVariableRegistry(org.apache.nifi.web.api.dto.VariableRegistryDTO)) && "
+ "args(groupId)")
public void updateVariableRegistryAdvice(ProceedingJoinPoint proceedingJoinPoint, String groupId) throws Throwable {
final Operation operation = Operation.Configure;
saveUpdateAction(proceedingJoinPoint, groupId, operation);
+ "execution(org.apache.nifi.groups.ProcessGroup updateVariableRegistry(org.apache.nifi.authorization.user.NiFiUser, org.apache.nifi.web.api.dto.VariableRegistryDTO)) && "
+ "args(user, variableRegistry)")
public ProcessGroup updateVariableRegistryAdvice(final ProceedingJoinPoint proceedingJoinPoint, final NiFiUser user, final VariableRegistryDTO variableRegistry) throws Throwable {
final ProcessGroup updatedProcessGroup = (ProcessGroup) proceedingJoinPoint.proceed();
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();
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
FlowChangeAction action = new FlowChangeAction();
action.setUserIdentity(user.getIdentity());

View File

@ -16,14 +16,6 @@
*/
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.RequestAction;
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.ProcessorEntity;
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.RemoteProcessGroupEntity;
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.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.
*/
@ -1929,7 +1930,7 @@ public interface NiFiServiceFacade {
* @param registryDTO The registry 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.
@ -1937,14 +1938,14 @@ public interface NiFiServiceFacade {
* @param registryId id
* @return entity
*/
RegistryEntity getRegistryClient(String registryId);
RegistryClientEntity getRegistryClient(String registryId);
/**
* Returns all registry clients.
*
* @return registry clients
*/
Set<RegistryEntity> getRegistryClients();
Set<RegistryClientEntity> getRegistryClients();
/**
* Gets all registries for the current user.
@ -1991,7 +1992,7 @@ public interface NiFiServiceFacade {
* @param registryDTO the registry dto
* @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.
@ -2000,7 +2001,7 @@ public interface NiFiServiceFacade {
* @param registryId id
* @return the deleted registry entity
*/
RegistryEntity deleteRegistryClient(Revision revision, String registryId);
RegistryClientEntity deleteRegistryClient(Revision revision, String registryId);
/**
* 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.ProcessorEntity;
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.RemoteProcessGroupEntity;
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 RevisionUpdate<VariableRegistryDTO> snapshot = updateComponent(user, revision,
processGroupNode,
() -> processGroupDAO.updateVariableRegistry(variableRegistryDto),
() -> processGroupDAO.updateVariableRegistry(user, variableRegistryDto),
processGroup -> dtoFactory.createVariableRegistryDto(processGroup, revisionManager));
final PermissionsDTO permissions = dtoFactory.createPermissionsDto(processGroupNode);
@ -2301,10 +2302,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
@Override
public RegistryEntity createRegistryClient(Revision revision, RegistryDTO registryDTO) {
public RegistryClientEntity createRegistryClient(Revision revision, RegistryDTO registryDTO) {
final NiFiUser user = NiFiUserUtils.getNiFiUser();
// read lock on the containing group
// request claim for component to be created... revision already verified (version == 0)
final RevisionClaim claim = new StandardRevisionClaim(revision);
@ -2321,52 +2321,25 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
});
final FlowRegistry registry = revisionUpdate.getComponent();
return createRegistryEntity(registry);
return createRegistryClientEntity(registry);
}
@Override
public RegistryEntity getRegistryClient(final String registryId) {
public RegistryClientEntity getRegistryClient(final String 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) {
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 Revision revision = revisionManager.getRevision(dto.getId());
final RegistryEntity entity = new RegistryEntity();
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;
return entityFactory.createRegistryClientEntity(dto, revision, permissions);
}
private VersionedFlowEntity createVersionedFlowEntity(final String registryId, final VersionedFlow versionedFlow) {
@ -2400,23 +2373,40 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@Override
public Set<RegistryEntity> getRegistryClients() {
public Set<RegistryClientEntity> getRegistryClients() {
return registryDAO.getFlowRegistries().stream()
.map(this::createRegistryEntity)
.map(this::createRegistryClientEntity)
.collect(Collectors.toSet());
}
@Override
public Set<RegistryEntity> getRegistriesForUser(final NiFiUser user) {
return registryDAO.getFlowRegistriesForUser(user).stream()
.map(this::createRegistryEntity)
.map(flowRegistry -> entityFactory.createRegistryEntity(dtoFactory.createRegistryDto(flowRegistry)))
.collect(Collectors.toSet());
}
@Override
public Set<BucketEntity> getBucketsForUser(final String registryId, final NiFiUser user) {
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());
}
@ -2435,7 +2425,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@Override
public RegistryEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO) {
public RegistryClientEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO) {
final RevisionClaim revisionClaim = new StandardRevisionClaim(revision);
final NiFiUser user = NiFiUserUtils.getNiFiUser();
@ -2454,7 +2444,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
});
final FlowRegistry updatedReg = revisionUpdate.getComponent();
return createRegistryEntity(updatedReg);
return createRegistryClientEntity(updatedReg);
}
@Override
@ -2463,7 +2453,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@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 NiFiUser user = NiFiUserUtils.getNiFiUser();
@ -2473,7 +2463,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
return reg;
});
return createRegistryEntity(registry);
return createRegistryClientEntity(registry);
}
@Override
@ -3695,10 +3685,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
// add first snapshot to the flow in the registry
registeredSnapshot = registerVersionedFlowSnapshot(registryId, registeredFlow, versionedProcessGroup, versionedFlowDto.getComments(), expectedVersion);
} catch (final NiFiRegistryException e) {
throw new IllegalArgumentException(e);
throw new IllegalArgumentException(e.getLocalizedMessage());
} catch (final IOException ioe) {
// will result in a 500: Internal Server Error
throw new RuntimeException("Failed to communicate with Flow Registry when attempting to " + action);
throw new IllegalStateException("Failed to communicate with Flow Registry when attempting to " + action);
}
final Bucket bucket = registeredSnapshot.getBucket();
@ -4105,7 +4094,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ProcessGroup processGroupNode = processGroupDAO.getProcessGroup(groupId);
final RevisionUpdate<ProcessGroupDTO> snapshot = updateComponent(user, revision,
processGroupNode,
() -> processGroupDAO.updateProcessGroupFlow(groupId, proposedFlowSnapshot, versionControlInfo, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows),
() -> processGroupDAO.updateProcessGroupFlow(groupId, user, proposedFlowSnapshot, versionControlInfo, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows),
processGroup -> dtoFactory.createProcessGroupDto(processGroup));
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.HistoryEntity;
import org.apache.nifi.web.api.entity.NodeEntity;
import org.apache.nifi.web.api.entity.RegistriesEntity;
import org.apache.nifi.web.api.entity.RegistryEntity;
import org.apache.nifi.web.api.entity.RegistryClientsEntity;
import org.apache.nifi.web.api.entity.RegistryClientEntity;
import org.apache.nifi.web.api.entity.ReportingTaskEntity;
import org.apache.nifi.web.api.request.ClientIdParameter;
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.
*
* @param registryEntity registry
* @param registryClientEntity registry
* @return dtos
*/
public RegistryEntity populateRemainingRegistryEntityContent(final RegistryEntity registryEntity) {
registryEntity.setUri(generateResourceUri("controller", "registry-clients", registryEntity.getId()));
return registryEntity;
public RegistryClientEntity populateRemainingRegistryEntityContent(final RegistryClientEntity registryClientEntity) {
registryClientEntity.setUri(generateResourceUri("controller", "registry-clients", registryClientEntity.getId()));
return registryClientEntity;
}
/**
@ -316,7 +316,7 @@ public class ControllerResource extends ApplicationResource {
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@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")
})
@ApiResponses(value = {
@ -333,10 +333,10 @@ public class ControllerResource extends ApplicationResource {
return replicate(HttpMethod.GET);
}
final Set<RegistryEntity> registries = serviceFacade.getRegistryClients();
final Set<RegistryClientEntity> registries = serviceFacade.getRegistryClients();
registries.forEach(registry -> populateRemainingRegistryEntityContent(registry));
final RegistriesEntity registryEntities = new RegistriesEntity();
final RegistryClientsEntity registryEntities = new RegistryClientsEntity();
registryEntities.setRegistries(registries);
return generateOkResponse(registryEntities).build();
@ -346,8 +346,8 @@ public class ControllerResource extends ApplicationResource {
* Creates a new Registry.
*
* @param httpServletRequest request
* @param requestRegistryEntity A registryEntity.
* @return A registryEntity.
* @param requestRegistryClientEntity A registryClientEntity.
* @return A registryClientEntity.
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@ -355,7 +355,7 @@ public class ControllerResource extends ApplicationResource {
@Path("registry-clients")
@ApiOperation(
value = "Creates a new registry client",
response = RegistryEntity.class,
response = RegistryClientEntity.class,
authorizations = {
@Authorization(value = "Write - /controller")
}
@ -373,28 +373,28 @@ public class ControllerResource extends ApplicationResource {
@ApiParam(
value = "The registry configuration details.",
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.");
}
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.");
}
final RegistryDTO requestReportingTask = requestRegistryEntity.getComponent();
final RegistryDTO requestReportingTask = requestRegistryClientEntity.getComponent();
if (requestReportingTask.getId() != null) {
throw new IllegalArgumentException("Registry ID cannot be specified.");
}
if (isReplicateRequest()) {
return replicate(HttpMethod.POST, requestRegistryEntity);
return replicate(HttpMethod.POST, requestRegistryClientEntity);
}
return withWriteLock(
serviceFacade,
requestRegistryEntity,
requestRegistryClientEntity,
lookup -> {
authorizeController(RequestAction.WRITE);
},
@ -407,7 +407,7 @@ public class ControllerResource extends ApplicationResource {
// create the reporting task and generate the json
final Revision revision = getRevision(registryEntity, registry.getId());
final RegistryEntity entity = serviceFacade.createRegistryClient(revision, registry);
final RegistryClientEntity entity = serviceFacade.createRegistryClient(revision, registry);
populateRemainingRegistryEntityContent(entity);
// build the response
@ -420,7 +420,7 @@ public class ControllerResource extends ApplicationResource {
* Retrieves the specified registry.
*
* @param id The id of the registry to retrieve
* @return A registryEntity.
* @return A registryClientEntity.
*/
@GET
@Consumes(MediaType.WILDCARD)
@ -428,7 +428,7 @@ public class ControllerResource extends ApplicationResource {
@Path("/registry-clients/{id}")
@ApiOperation(
value = "Gets a registry client",
response = RegistryEntity.class,
response = RegistryClientEntity.class,
authorizations = {
@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.")
}
)
public Response getRegistry(
public Response getRegistryClient(
@ApiParam(
value = "The registry id.",
required = true
@ -457,7 +457,7 @@ public class ControllerResource extends ApplicationResource {
authorizeController(RequestAction.READ);
// get the registry
final RegistryEntity entity = serviceFacade.getRegistryClient(id);
final RegistryClientEntity entity = serviceFacade.getRegistryClient(id);
populateRemainingRegistryEntityContent(entity);
return generateOkResponse(entity).build();
@ -477,7 +477,7 @@ public class ControllerResource extends ApplicationResource {
@Path("/registry-clients/{id}")
@ApiOperation(
value = "Updates a registry client",
response = RegistryEntity.class,
response = RegistryClientEntity.class,
authorizations = {
@Authorization(value = "Write - /controller")
}
@ -501,7 +501,7 @@ public class ControllerResource extends ApplicationResource {
@ApiParam(
value = "The registry configuration details.",
required = true
) final RegistryEntity requestRegsitryEntity) {
) final RegistryClientEntity requestRegsitryEntity) {
if (requestRegsitryEntity == null || requestRegsitryEntity.getComponent() == null) {
throw new IllegalArgumentException("Registry details must be specified.");
@ -536,7 +536,7 @@ public class ControllerResource extends ApplicationResource {
final RegistryDTO registry = registryEntity.getComponent();
// update the controller service
final RegistryEntity entity = serviceFacade.updateRegistryClient(revision, registry);
final RegistryClientEntity entity = serviceFacade.updateRegistryClient(revision, registry);
populateRemainingRegistryEntityContent(entity);
return generateOkResponse(entity).build();
@ -562,7 +562,7 @@ public class ControllerResource extends ApplicationResource {
@Path("/registry-clients/{id}")
@ApiOperation(
value = "Deletes a registry client",
response = RegistryEntity.class,
response = RegistryClientEntity.class,
authorizations = {
@Authorization(value = "Write - /controller")
}
@ -598,14 +598,14 @@ public class ControllerResource extends ApplicationResource {
return replicate(HttpMethod.DELETE);
}
final RegistryEntity requestRegistryEntity = new RegistryEntity();
requestRegistryEntity.setId(id);
final RegistryClientEntity requestRegistryClientEntity = new RegistryClientEntity();
requestRegistryClientEntity.setId(id);
// handle expects request (usually from the cluster manager)
final Revision requestRevision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
return withWriteLock(
serviceFacade,
requestRegistryEntity,
requestRegistryClientEntity,
requestRevision,
lookup -> {
authorizeController(RequestAction.WRITE);
@ -613,7 +613,7 @@ public class ControllerResource extends ApplicationResource {
() -> serviceFacade.verifyDeleteRegistry(id),
(revision, registryEntity) -> {
// delete the specified registry
final RegistryEntity entity = serviceFacade.deleteRegistryClient(revision, registryEntity.getId());
final RegistryClientEntity entity = serviceFacade.deleteRegistryClient(revision, registryEntity.getId());
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.ProcessorTypesEntity;
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.RemoteProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ReportingTaskEntity;
@ -1316,7 +1317,7 @@ public class FlowResource extends ApplicationResource {
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@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")
})
@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.")
})
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()) {
return replicate(HttpMethod.POST);
@ -412,7 +412,7 @@ public class VersionsResource extends ApplicationResource {
})
public Response saveToFlowRegistry(
@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
final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();
@ -569,8 +569,9 @@ public class VersionsResource extends ApplicationResource {
return requestId;
}
private void replicateVersionControlMapping(final VersionControlComponentMappingEntity mappingEntity, final StartVersionControlRequestEntity requestEntity, final URI requestUri,
final String groupId) {
private void replicateVersionControlMapping(final VersionControlComponentMappingEntity mappingEntity, final StartVersionControlRequestEntity requestEntity,
final URI requestUri, final String groupId) {
final Map<String, String> headers = new HashMap<>();
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.",
required = false)
@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()) {
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.")
})
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
final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();

View File

@ -272,10 +272,10 @@ public final class DtoFactory {
actionDto.setId(action.getId());
actionDto.setSourceId(action.getSourceId());
actionDto.setSourceName(action.getSourceName());
actionDto.setSourceType(action.getSourceType().name());
actionDto.setSourceType(action.getSourceType().toString());
actionDto.setTimestamp(action.getTimestamp());
actionDto.setUserIdentity(action.getUserIdentity());
actionDto.setOperation(action.getOperation().name());
actionDto.setOperation(action.getOperation().toString());
actionDto.setActionDetails(createActionDetailsDto(action.getActionDetails()));
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.AffectedComponentEntity;
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.ComponentReferenceEntity;
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.ProcessorStatusEntity;
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.RemoteProcessGroupPortEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
@ -546,4 +549,43 @@ public final class EntityFactory {
entity.setProcessGroupRevision(processGroupRevision);
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;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.groups.ProcessGroup;
@ -118,7 +119,7 @@ public interface ProcessGroupDAO {
* update the contents of that 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);
/**
@ -141,10 +142,11 @@ public interface ProcessGroupDAO {
/**
* Updates the specified variable registry
*
* @param user the user performing the update
* @param variableRegistry the Variable Registry
* @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

View File

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

View File

@ -16,6 +16,7 @@
*/
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.Port;
import org.apache.nifi.connectable.Position;
@ -143,7 +144,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
}
@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);
CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
@ -275,8 +276,9 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
}
@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 ProcessGroup group = locateProcessGroup(flowController, groupId);
group.updateFlow(proposedSnapshot, componentIdSeed, verifyNotModified, updateSettings, updateDescendantVersionedFlows);
@ -291,7 +293,7 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
}
@Override
public ProcessGroup updateVariableRegistry(final VariableRegistryDTO variableRegistry) {
public ProcessGroup updateVariableRegistry(final NiFiUser user, final VariableRegistryDTO variableRegistry) {
final ProcessGroup group = locateProcessGroup(flowController, variableRegistry.getProcessGroupId());
if (group == null) {
throw new ResourceNotFoundException("Could not find Process Group with ID " + variableRegistry.getProcessGroupId());

View File

@ -80,6 +80,7 @@
</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 id="new-variable-dialog" class="dialog cancellable small-dialog hidden">
<div class="dialog-content">

View File

@ -15,7 +15,7 @@
limitations under the License.
--%>
<%@ 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 id="nf-ok-dialog-content"></div>
</div>

View File

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

View File

@ -43,6 +43,15 @@
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 {
max-height: 72%;
max-width: 55%;

View File

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

View File

@ -180,9 +180,11 @@
* @param registryCombo
* @param bucketCombo
* @param flowCombo
* @param selectBucket
* @param bucketCheck
* @returns {deferred}
*/
var loadRegistries = function (dialog, registryCombo, bucketCombo, flowCombo, selectBucket) {
var loadRegistries = function (dialog, registryCombo, bucketCombo, flowCombo, selectBucket, bucketCheck) {
return $.ajax({
type: 'GET',
url: '../nifi-api/flow/registries',
@ -192,11 +194,11 @@
if (nfCommon.isDefinedAndNotNull(registriesResponse.registries) && registriesResponse.registries.length > 0) {
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) {
var registry = registryEntity.component;
var registry = registryEntity.registry;
registries.push({
text: registry.name,
value: registry.id,
@ -216,7 +218,7 @@
registryCombo.combo({
options: registries,
select: function (selectedOption) {
selectRegistry(dialog, selectedOption, bucketCombo, flowCombo, selectBucket)
selectRegistry(dialog, selectedOption, bucketCombo, flowCombo, selectBucket, bucketCheck)
}
});
}).fail(nfErrorHandler.handleAjaxError);
@ -229,9 +231,10 @@
* @param bucketCombo
* @param flowCombo
* @param selectBucket
* @param bucketCheck
* @returns {*}
*/
var loadBuckets = function (registryIdentifier, bucketCombo, flowCombo, selectBucket) {
var loadBuckets = function (registryIdentifier, bucketCombo, flowCombo, selectBucket, bucketCheck) {
return $.ajax({
type: 'GET',
url: '../nifi-api/flow/registries/' + encodeURIComponent(registryIdentifier) + '/buckets',
@ -241,18 +244,33 @@
if (nfCommon.isDefinedAndNotNull(response.buckets) && response.buckets.length > 0) {
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;
});
$.each(response.buckets, function (_, bucketEntity) {
if (bucketEntity.permissions.canRead === true) {
var bucket = bucketEntity.bucket;
if (bucketCheck(bucketEntity)) {
buckets.push({
text: bucket.name,
value: bucket.id,
description: nfCommon.escapeHtml(bucket.description)
});
}
}
});
} else {
}
if (buckets.length === 0) {
buckets.push({
text: 'No available buckets',
value: null,
@ -285,8 +303,9 @@
* @param bucketCombo
* @param flowCombo
* @param selectBucket
* @param bucketCheck
*/
var selectRegistry = function (dialog, selectedOption, bucketCombo, flowCombo, selectBucket) {
var selectRegistry = function (dialog, selectedOption, bucketCombo, flowCombo, selectBucket, bucketCheck) {
var showNoBucketsAvailable = function () {
bucketCombo.combo('destroy').combo({
options: [{
@ -333,7 +352,7 @@
clearFlowVersionsGrid();
}
loadBuckets(selectedOption.value, bucketCombo, flowCombo, selectBucket).fail(function () {
loadBuckets(selectedOption.value, bucketCombo, flowCombo, selectBucket, bucketCheck).fail(function () {
showNoBucketsAvailable();
});
}
@ -744,7 +763,9 @@
}]
}).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
$('#import-flow-version-dialog').modal('setHeaderText', 'Import Version').modal('setButtonModel', [{
buttonText: 'Import',
@ -904,6 +925,10 @@
* @param selectedBucket
*/
var selectBucketImportVersion = function (selectedBucket) {
// clear the flow versions grid
clearFlowVersionsGrid();
if (nfCommon.isDefinedAndNotNull(selectedBucket.value)) {
// mark the flows as loading
$('#import-flow-version-name-combo').combo('destroy').combo({
options: [{
@ -914,13 +939,21 @@
}]
});
// clear the flow versions grid
clearFlowVersionsGrid();
var selectedRegistry = $('#import-flow-version-registry-combo').combo('getSelectedOption');
// load the flows for the currently selected registry and bucket
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');
if (nfCommon.isDefinedAndNotNull(importFlowVersionGrid)) {
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;
}
} else {
return true;
}
@ -1731,7 +1779,9 @@
// reposition the version label
$('#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();
}).fail(function () {
deferred.reject();

View File

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