NIFI-4436:

- Added the import dialog for importing a versioned flow into a new process group.
- Added the change version dialog for upgrading/downgrading a versioned flow.
This commit is contained in:
Matt Gilman 2017-11-01 17:21:04 -04:00 committed by Bryan Bende
parent 6aa8b5c61c
commit 696d583b14
No known key found for this signature in database
GPG Key ID: A0DDA9ED50711C39
36 changed files with 1699 additions and 405 deletions

View File

@ -32,7 +32,6 @@ public class FlowConfigurationDTO {
private Boolean supportsManagedAuthorizer;
private Boolean supportsConfigurableAuthorizer;
private Boolean supportsConfigurableUsersAndGroups;
private Boolean supportsFlowVersioning;
private Long autoRefreshIntervalSeconds;
private Date currentTime;
@ -129,17 +128,4 @@ public class FlowConfigurationDTO {
this.timeOffset = timeOffset;
}
/**
* @return whether this NiFi is configured for support flow versioning
*/
@ApiModelProperty(
value = "Whether this NiFi supports flow versioning."
)
public Boolean getSupportsFlowVersioning() {
return supportsFlowVersioning;
}
public void setSupportsFlowVersioning(Boolean supportsFlowVersioning) {
this.supportsFlowVersioning = supportsFlowVersioning;
}
}

View File

@ -27,6 +27,7 @@ public class VersionControlInformationDTO {
private String registryId;
private String bucketId;
private String flowId;
private String flowName;
private Integer version;
private Boolean modified;
private Boolean current;
@ -67,6 +68,15 @@ public class VersionControlInformationDTO {
this.flowId = flowId;
}
@ApiModelProperty("The name of the flow")
public String getFlowName() {
return flowName;
}
public void setFlowName(String flowName) {
this.flowName = flowName;
}
@ApiModelProperty("The version of the flow")
public Integer getVersion() {
return version;

View File

@ -38,6 +38,8 @@ public class CurrentUserEntity extends Entity {
private PermissionsDTO systemPermissions;
private PermissionsDTO restrictedComponentsPermissions;
private boolean canVersionFlows;
/**
* @return the user identity being serialized
*/
@ -145,4 +147,16 @@ public class CurrentUserEntity extends Entity {
public void setRestrictedComponentsPermissions(PermissionsDTO restrictedComponentsPermissions) {
this.restrictedComponentsPermissions = restrictedComponentsPermissions;
}
/**
* @return whether the current user can version flows
*/
@ApiModelProperty("Whether the current user can version flows.")
public boolean isCanVersionFlows() {
return canVersionFlows;
}
public void setCanVersionFlows(boolean canVersionFlows) {
this.canVersionFlows = canVersionFlows;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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 io.swagger.annotations.ApiModelProperty;
import org.apache.nifi.web.api.dto.RevisionDTO;
import org.apache.nifi.web.api.dto.VersionedFlowDTO;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "versionedFlow")
public class StartVersionControlRequestEntity extends Entity {
private VersionedFlowDTO versionedFlow;
private RevisionDTO processGroupRevision;
@ApiModelProperty("The versioned flow")
public VersionedFlowDTO getVersionedFlow() {
return versionedFlow;
}
public void setVersionedFlow(VersionedFlowDTO versionedFLow) {
this.versionedFlow = versionedFLow;
}
@ApiModelProperty("The Revision of the Process Group under Version Control")
public RevisionDTO getProcessGroupRevision() {
return processGroupRevision;
}
public void setProcessGroupRevision(final RevisionDTO revision) {
this.processGroupRevision = revision;
}
}

View File

@ -18,7 +18,6 @@
package org.apache.nifi.web.api.entity;
import io.swagger.annotations.ApiModelProperty;
import org.apache.nifi.web.api.dto.RevisionDTO;
import org.apache.nifi.web.api.dto.VersionedFlowDTO;
import javax.xml.bind.annotation.XmlRootElement;
@ -26,7 +25,6 @@ import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "versionedFlow")
public class VersionedFlowEntity extends Entity {
private VersionedFlowDTO versionedFlow;
private RevisionDTO processGroupRevision;
@ApiModelProperty("The versioned flow")
public VersionedFlowDTO getVersionedFlow() {
@ -36,13 +34,4 @@ public class VersionedFlowEntity extends Entity {
public void setVersionedFlow(VersionedFlowDTO versionedFLow) {
this.versionedFlow = versionedFLow;
}
@ApiModelProperty("The Revision of the Process Group under Version Control")
public RevisionDTO getProcessGroupRevision() {
return processGroupRevision;
}
public void setProcessGroupRevision(final RevisionDTO revision) {
this.processGroupRevision = revision;
}
}

View File

@ -0,0 +1,47 @@
/*
* 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 io.swagger.annotations.ApiModelProperty;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "versionedFlowSnapshotMetadata")
public class VersionedFlowSnapshotMetadataEntity extends Entity {
private VersionedFlowSnapshotMetadata versionedFlowSnapshotMetadata;
private String registryId;
@ApiModelProperty("The collection of versioned flow snapshot metadata")
public VersionedFlowSnapshotMetadata getVersionedFlowSnapshotMetadata() {
return versionedFlowSnapshotMetadata;
}
public void setVersionedFlowMetadata(VersionedFlowSnapshotMetadata versionedFlowSnapshotMetadata) {
this.versionedFlowSnapshotMetadata = versionedFlowSnapshotMetadata;
}
@ApiModelProperty("The ID of the Registry that this flow belongs to")
public String getRegistryId() {
return registryId;
}
public void setRegistryId(String registryId) {
this.registryId = registryId;
}
}

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 javax.xml.bind.annotation.XmlRootElement;
import java.util.Set;
@XmlRootElement(name = "versionedFlowSnapshotMetadataSetEntity")
public class VersionedFlowSnapshotMetadataSetEntity extends Entity {
private Set<VersionedFlowSnapshotMetadataEntity> versionedFlowSnapshotMetadataSet;
/**
* @return collection of VersionedFlowSnapshotMetadataEntity's that are being serialized
*/
public Set<VersionedFlowSnapshotMetadataEntity> getVersionedFlowSnapshotMetadataSet() {
return versionedFlowSnapshotMetadataSet;
}
public void setVersionedFlowSnapshotMetadataSet(Set<VersionedFlowSnapshotMetadataEntity> versionedFlowSnapshotMetadataSet) {
this.versionedFlowSnapshotMetadataSet = versionedFlowSnapshotMetadataSet;
}
}

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 javax.xml.bind.annotation.XmlRootElement;
import java.util.Set;
@XmlRootElement(name = "versionedFlowsEntity")
public class VersionedFlowsEntity extends Entity {
private Set<VersionedFlowEntity> versionedFlows;
/**
* @return collection of VersionedEntity's that are being serialized
*/
public Set<VersionedFlowEntity> getVersionedFlows() {
return versionedFlows;
}
public void setVersionedFlows(Set<VersionedFlowEntity> versionedFlows) {
this.versionedFlows = versionedFlows;
}
}

View File

@ -77,6 +77,7 @@ import org.apache.nifi.web.api.entity.AccessPolicyEntity;
import org.apache.nifi.web.api.entity.ActionEntity;
import org.apache.nifi.web.api.entity.ActivateControllerServicesEntity;
import org.apache.nifi.web.api.entity.AffectedComponentEntity;
import org.apache.nifi.web.api.entity.BucketEntity;
import org.apache.nifi.web.api.entity.BulletinEntity;
import org.apache.nifi.web.api.entity.ConnectionEntity;
import org.apache.nifi.web.api.entity.ConnectionStatusEntity;
@ -103,6 +104,7 @@ import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
import org.apache.nifi.web.api.entity.ReportingTaskEntity;
import org.apache.nifi.web.api.entity.ScheduleComponentsEntity;
import org.apache.nifi.web.api.entity.SnippetEntity;
import org.apache.nifi.web.api.entity.StartVersionControlRequestEntity;
import org.apache.nifi.web.api.entity.StatusHistoryEntity;
import org.apache.nifi.web.api.entity.TemplateEntity;
import org.apache.nifi.web.api.entity.UserEntity;
@ -111,6 +113,7 @@ import org.apache.nifi.web.api.entity.VariableRegistryEntity;
import org.apache.nifi.web.api.entity.VersionControlComponentMappingEntity;
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;
@ -1300,7 +1303,7 @@ public interface NiFiServiceFacade {
* @return a VersionControlComponentMappingEntity that contains the information needed to notify a Process Group where it is tracking to and map
* component ID's to their Versioned Component ID's
*/
VersionControlComponentMappingEntity registerFlowWithFlowRegistry(String groupId, VersionedFlowEntity requestEntity);
VersionControlComponentMappingEntity registerFlowWithFlowRegistry(String groupId, StartVersionControlRequestEntity requestEntity);
/**
* Adds the given snapshot to the already existing Versioned Flow, which resides in the given Flow Registry with the given id
@ -1854,7 +1857,7 @@ public interface NiFiServiceFacade {
* @param registryDTO The registry DTO
* @return The reporting task DTO
*/
RegistryEntity createRegistry(Revision revision, RegistryDTO registryDTO);
RegistryEntity createRegistryClient(Revision revision, RegistryDTO registryDTO);
/**
* Gets a registry with the specified id.
@ -1862,14 +1865,52 @@ public interface NiFiServiceFacade {
* @param registryId id
* @return entity
*/
RegistryEntity getRegistry(String registryId);
RegistryEntity getRegistryClient(String registryId);
/**
* Gets all registries.
* Returns all registry clients.
*
* @return registry clients
*/
Set<RegistryEntity> getRegistryClients();
/**
* Gets all registries for the current user.
*
* @param user current user
* @return registries
*/
Set<RegistryEntity> getRegistries();
Set<RegistryEntity> getRegistriesForUser(NiFiUser user);
/**
* Gets all buckets for a given registry.
*
* @param registryId registry id
* @param user current user
* @return the buckets
*/
Set<BucketEntity> getBucketsForUser(String registryId, NiFiUser user);
/**
* Gets the flows for the current user for the specified registry and bucket.
*
* @param registryId registry id
* @param bucketId bucket id
* @param user current user
* @return the flows
*/
Set<VersionedFlowEntity> getFlowsForUser(String registryId, String bucketId, NiFiUser user);
/**
* Gets the versions of the specified registry, bucket, and flow for the current user.
*
* @param registryId registry id
* @param bucketId bucket id
* @param flowId flow id
* @param user current user
* @return the versions of the flow
*/
Set<VersionedFlowSnapshotMetadataEntity> getFlowVersionsForUser(String registryId, String bucketId, String flowId, NiFiUser user);
/**
* Updates the specified registry using the specified revision.
@ -1878,7 +1919,7 @@ public interface NiFiServiceFacade {
* @param registryDTO the registry dto
* @return the updated registry registry entity
*/
RegistryEntity updateRegistry(Revision revision, RegistryDTO registryDTO);
RegistryEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO);
/**
* Deletes the specified registry using the specified revision.
@ -1887,7 +1928,14 @@ public interface NiFiServiceFacade {
* @param registryId id
* @return the deleted registry entity
*/
RegistryEntity deleteRegistry(Revision revision, String registryId);
RegistryEntity deleteRegistryClient(Revision revision, String registryId);
/**
* Verifies the specified registry can be removed.
*
* @param registryId the registry id
*/
void verifyDeleteRegistry(String registryId);
// ----------------------------------------
// History methods

View File

@ -16,32 +16,8 @@
*/
package org.apache.nifi.web;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.nifi.action.Action;
import org.apache.nifi.action.Component;
import org.apache.nifi.action.FlowChangeAction;
@ -111,15 +87,17 @@ import org.apache.nifi.history.History;
import org.apache.nifi.history.HistoryQuery;
import org.apache.nifi.history.PreviousValue;
import org.apache.nifi.registry.ComponentVariableRegistry;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.flow.FlowRegistry;
import org.apache.nifi.registry.flow.FlowRegistryClient;
import org.apache.nifi.registry.flow.VersionedFlowCoordinates;
import org.apache.nifi.registry.flow.UnknownResourceException;
import org.apache.nifi.registry.flow.VersionControlInformation;
import org.apache.nifi.registry.flow.VersionedComponent;
import org.apache.nifi.registry.flow.VersionedConnection;
import org.apache.nifi.registry.flow.VersionedFlow;
import org.apache.nifi.registry.flow.VersionedFlowCoordinates;
import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
import org.apache.nifi.registry.flow.VersionedProcessGroup;
import org.apache.nifi.registry.flow.diff.ComparableDataFlow;
import org.apache.nifi.registry.flow.diff.DifferenceType;
@ -144,6 +122,7 @@ import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.api.dto.AccessPolicyDTO;
import org.apache.nifi.web.api.dto.AccessPolicySummaryDTO;
import org.apache.nifi.web.api.dto.AffectedComponentDTO;
import org.apache.nifi.web.api.dto.BucketDTO;
import org.apache.nifi.web.api.dto.BulletinBoardDTO;
import org.apache.nifi.web.api.dto.BulletinDTO;
import org.apache.nifi.web.api.dto.BulletinQueryDTO;
@ -215,6 +194,7 @@ import org.apache.nifi.web.api.entity.AccessPolicySummaryEntity;
import org.apache.nifi.web.api.entity.ActionEntity;
import org.apache.nifi.web.api.entity.ActivateControllerServicesEntity;
import org.apache.nifi.web.api.entity.AffectedComponentEntity;
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;
@ -253,7 +233,9 @@ import org.apache.nifi.web.api.entity.VariableEntity;
import org.apache.nifi.web.api.entity.VariableRegistryEntity;
import org.apache.nifi.web.api.entity.VersionControlComponentMappingEntity;
import org.apache.nifi.web.api.entity.VersionControlInformationEntity;
import org.apache.nifi.web.api.entity.StartVersionControlRequestEntity;
import org.apache.nifi.web.api.entity.VersionedFlowEntity;
import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataEntity;
import org.apache.nifi.web.controller.ControllerFacade;
import org.apache.nifi.web.dao.AccessPolicyDAO;
import org.apache.nifi.web.dao.ConnectionDAO;
@ -282,7 +264,30 @@ import org.apache.nifi.web.util.SnippetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Sets;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* Implementation of NiFiServiceFacade that performs revision checking.
@ -2268,7 +2273,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
@Override
public RegistryEntity createRegistry(Revision revision, RegistryDTO registryDTO) {
public RegistryEntity createRegistryClient(Revision revision, RegistryDTO registryDTO) {
final NiFiUser user = NiFiUserUtils.getNiFiUser();
// read lock on the containing group
@ -2292,7 +2297,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@Override
public RegistryEntity getRegistry(final String registryId) {
public RegistryEntity getRegistryClient(final String registryId) {
final FlowRegistry registry = registryDAO.getFlowRegistry(registryId);
return createRegistryEntity(registry);
}
@ -2319,15 +2324,90 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
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) {
if (versionedFlow == null) {
return null;
}
final VersionedFlowDTO dto = new VersionedFlowDTO();
dto.setRegistryId(registryId);
dto.setBucketId(versionedFlow.getBucketIdentifier());
dto.setFlowId(versionedFlow.getIdentifier());
dto.setFlowName(versionedFlow.getName());
dto.setDescription(versionedFlow.getDescription());
final VersionedFlowEntity entity = new VersionedFlowEntity();
entity.setVersionedFlow(dto);
return entity;
}
private VersionedFlowSnapshotMetadataEntity createVersionedFlowSnapshotMetadataEntity(final String registryId, final VersionedFlowSnapshotMetadata metadata) {
if (metadata == null) {
return null;
}
final VersionedFlowSnapshotMetadataEntity entity = new VersionedFlowSnapshotMetadataEntity();
entity.setRegistryId(registryId);
entity.setVersionedFlowMetadata(metadata);
return entity;
}
@Override
public Set<RegistryEntity> getRegistries() {
public Set<RegistryEntity> getRegistryClients() {
return registryDAO.getFlowRegistries().stream()
.map(this::createRegistryEntity)
.collect(Collectors.toSet());
}
@Override
public RegistryEntity updateRegistry(Revision revision, RegistryDTO registryDTO) {
public Set<RegistryEntity> getRegistriesForUser(final NiFiUser user) {
return registryDAO.getFlowRegistriesForUser(user).stream()
.map(this::createRegistryEntity)
.collect(Collectors.toSet());
}
@Override
public Set<BucketEntity> getBucketsForUser(final String registryId, final NiFiUser user) {
return registryDAO.getBucketsForUser(registryId, user).stream()
.map(this::createBucketEntity)
.collect(Collectors.toSet());
}
@Override
public Set<VersionedFlowEntity> getFlowsForUser(String registryId, String bucketId, NiFiUser user) {
return registryDAO.getFlowsForUser(registryId, bucketId, user).stream()
.map(vf -> createVersionedFlowEntity(registryId, vf))
.collect(Collectors.toSet());
}
@Override
public Set<VersionedFlowSnapshotMetadataEntity> getFlowVersionsForUser(String registryId, String bucketId, String flowId, NiFiUser user) {
return registryDAO.getFlowVersionsForUser(registryId, bucketId, flowId, user).stream()
.map(md -> createVersionedFlowSnapshotMetadataEntity(registryId, md))
.collect(Collectors.toSet());
}
@Override
public RegistryEntity updateRegistryClient(Revision revision, RegistryDTO registryDTO) {
final RevisionClaim revisionClaim = new StandardRevisionClaim(revision);
final NiFiUser user = NiFiUserUtils.getNiFiUser();
@ -2350,7 +2430,12 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@Override
public RegistryEntity deleteRegistry(final Revision revision, final String registryId) {
public void verifyDeleteRegistry(String registryId) {
processGroupDAO.verifyDeleteFlowRegistry(registryId);
}
@Override
public RegistryEntity deleteRegistryClient(final Revision revision, final String registryId) {
final RevisionClaim claim = new StandardRevisionClaim(revision);
final NiFiUser user = NiFiUserUtils.getNiFiUser();
@ -3340,6 +3425,10 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
entity.setPoliciesPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getPolicies()));
entity.setSystemPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getSystem()));
entity.setRestrictedComponentsPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getRestrictedComponents()));
// TODO - update to be user specific
entity.setCanVersionFlows(CollectionUtils.isNotEmpty(flowRegistryClient.getRegistryIdentifiers()));
return entity;
}
@ -3538,7 +3627,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
}
@Override
public VersionControlComponentMappingEntity registerFlowWithFlowRegistry(final String groupId, final VersionedFlowEntity requestEntity) {
public VersionControlComponentMappingEntity registerFlowWithFlowRegistry(final String groupId, final StartVersionControlRequestEntity requestEntity) {
// Create a VersionedProcessGroup snapshot of the flow as it is currently.
final InstantiatedVersionedProcessGroup versionedProcessGroup = createFlowSnapshot(groupId);
@ -3584,6 +3673,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
vci.setBucketId(registeredFlow.getBucketIdentifier());
vci.setCurrent(true);
vci.setFlowId(registeredFlow.getIdentifier());
vci.setFlowName(registeredFlow.getName());
vci.setGroupId(groupId);
vci.setModified(false);
vci.setRegistryId(registryId);

View File

@ -46,6 +46,7 @@ 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.ReportingTaskEntity;
import org.apache.nifi.web.api.request.ClientIdParameter;
@ -69,6 +70,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.net.URI;
import java.util.Date;
import java.util.Set;
/**
* RESTful endpoint for managing a Flow Controller.
@ -93,7 +95,7 @@ public class ControllerResource extends ApplicationResource {
* @return dtos
*/
public RegistryEntity populateRemainingRegistryEntityContent(final RegistryEntity registryEntity) {
registryEntity.setUri(generateResourceUri("controller", "registries", registryEntity.getId()));
registryEntity.setUri(generateResourceUri("controller", "registry-clients", registryEntity.getId()));
return registryEntity;
}
@ -310,6 +312,36 @@ public class ControllerResource extends ApplicationResource {
// registries
// ----------
@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("registry-clients")
@ApiOperation(value = "Gets the listing of available registry clients", response = RegistriesEntity.class, authorizations = {
@Authorization(value = "Read - /flow")
})
@ApiResponses(value = {
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
@ApiResponse(code = 401, message = "Client could not be authenticated."),
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
@ApiResponse(code = 404, message = "The specified resource could not be found."),
@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 getRegistryClients() {
authorizeController(RequestAction.READ);
if (isReplicateRequest()) {
return replicate(HttpMethod.GET);
}
final Set<RegistryEntity> registries = serviceFacade.getRegistryClients();
registries.forEach(registry -> populateRemainingRegistryEntityContent(registry));
final RegistriesEntity registryEntities = new RegistriesEntity();
registryEntities.setRegistries(registries);
return generateOkResponse(registryEntities).build();
}
/**
* Creates a new Registry.
*
@ -320,9 +352,9 @@ public class ControllerResource extends ApplicationResource {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("registries")
@Path("registry-clients")
@ApiOperation(
value = "Creates a new registry",
value = "Creates a new registry client",
response = RegistryEntity.class,
authorizations = {
@Authorization(value = "Write - /controller")
@ -336,8 +368,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 createRegistry(
public Response createRegistryClient(
@Context final HttpServletRequest httpServletRequest,
@ApiParam(
value = "The registry configuration details.",
@ -376,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.createRegistry(revision, registry);
final RegistryEntity entity = serviceFacade.createRegistryClient(revision, registry);
populateRemainingRegistryEntityContent(entity);
// build the response
@ -394,9 +425,9 @@ public class ControllerResource extends ApplicationResource {
@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("/registries/{id}")
@Path("/registry-clients/{id}")
@ApiOperation(
value = "Gets a registry",
value = "Gets a registry client",
response = RegistryEntity.class,
authorizations = {
@Authorization(value = "Read - /controller")
@ -426,7 +457,7 @@ public class ControllerResource extends ApplicationResource {
authorizeController(RequestAction.READ);
// get the registry
final RegistryEntity entity = serviceFacade.getRegistry(id);
final RegistryEntity entity = serviceFacade.getRegistryClient(id);
populateRemainingRegistryEntityContent(entity);
return generateOkResponse(entity).build();
@ -443,9 +474,9 @@ public class ControllerResource extends ApplicationResource {
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/registries/{id}")
@Path("/registry-clients/{id}")
@ApiOperation(
value = "Updates a registry",
value = "Updates a registry client",
response = RegistryEntity.class,
authorizations = {
@Authorization(value = "Write - /controller")
@ -460,7 +491,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 updateControllerService(
public Response updateRegistryClient(
@Context HttpServletRequest httpServletRequest,
@ApiParam(
value = "The registry id.",
@ -505,7 +536,7 @@ public class ControllerResource extends ApplicationResource {
final RegistryDTO registry = registryEntity.getComponent();
// update the controller service
final RegistryEntity entity = serviceFacade.updateRegistry(revision, registry);
final RegistryEntity entity = serviceFacade.updateRegistryClient(revision, registry);
populateRemainingRegistryEntityContent(entity);
return generateOkResponse(entity).build();
@ -528,9 +559,9 @@ public class ControllerResource extends ApplicationResource {
@DELETE
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("/registries/{id}")
@Path("/registry-clients/{id}")
@ApiOperation(
value = "Deletes a reistry",
value = "Deletes a registry client",
response = RegistryEntity.class,
authorizations = {
@Authorization(value = "Write - /controller")
@ -545,7 +576,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 deleteRegistry(
public Response deleteRegistryClient(
@Context HttpServletRequest httpServletRequest,
@ApiParam(
value = "The revision is used to verify the client is working with the latest version of the flow.",
@ -579,10 +610,10 @@ public class ControllerResource extends ApplicationResource {
lookup -> {
authorizeController(RequestAction.WRITE);
},
null,
() -> serviceFacade.verifyDeleteRegistry(id),
(revision, registryEntity) -> {
// delete the specified registry
final RegistryEntity entity = serviceFacade.deleteRegistry(revision, registryEntity.getId());
final RegistryEntity entity = serviceFacade.deleteRegistryClient(revision, registryEntity.getId());
return generateOkResponse(entity).build();
}
);

View File

@ -39,18 +39,13 @@ import org.apache.nifi.controller.service.ControllerServiceNode;
import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.nar.NarClassLoaders;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.flow.FlowRegistry;
import org.apache.nifi.registry.flow.FlowRegistryClient;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.IllegalClusterResourceRequestException;
import org.apache.nifi.web.NiFiCoreException;
import org.apache.nifi.web.NiFiServiceFacade;
import org.apache.nifi.web.ResourceNotFoundException;
import org.apache.nifi.web.Revision;
import org.apache.nifi.web.api.dto.AboutDTO;
import org.apache.nifi.web.api.dto.BannerDTO;
import org.apache.nifi.web.api.dto.BucketDTO;
import org.apache.nifi.web.api.dto.BulletinBoardDTO;
import org.apache.nifi.web.api.dto.BulletinQueryDTO;
import org.apache.nifi.web.api.dto.ClusterDTO;
@ -102,6 +97,10 @@ import org.apache.nifi.web.api.entity.SearchResultsEntity;
import org.apache.nifi.web.api.entity.StatusHistoryEntity;
import org.apache.nifi.web.api.entity.TemplateEntity;
import org.apache.nifi.web.api.entity.TemplatesEntity;
import org.apache.nifi.web.api.entity.VersionedFlowEntity;
import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataEntity;
import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataSetEntity;
import org.apache.nifi.web.api.entity.VersionedFlowsEntity;
import org.apache.nifi.web.api.request.BulletinBoardPatternParameter;
import org.apache.nifi.web.api.request.DateTimeParameter;
import org.apache.nifi.web.api.request.IntegerParameter;
@ -121,7 +120,6 @@ import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
@ -158,11 +156,8 @@ public class FlowResource extends ApplicationResource {
private TemplateResource templateResource;
private ProcessGroupResource processGroupResource;
private ControllerServiceResource controllerServiceResource;
private ControllerResource controllerResource;
private ReportingTaskResource reportingTaskResource;
private FlowRegistryClient flowRegistryClient;
public FlowResource() {
super();
}
@ -1351,12 +1346,7 @@ public class FlowResource extends ApplicationResource {
public Response getRegistries() {
authorizeFlow();
if (isReplicateRequest()) {
return replicate(HttpMethod.GET);
}
final Set<RegistryEntity> registries = serviceFacade.getRegistries();
registries.forEach(registry -> controllerResource.populateRemainingRegistryEntityContent(registry));
final Set<RegistryEntity> registries = serviceFacade.getRegistriesForUser(NiFiUserUtils.getNiFiUser());
final RegistriesEntity registryEntities = new RegistriesEntity();
registryEntities.setRegistries(registries);
@ -1387,39 +1377,89 @@ public class FlowResource extends ApplicationResource {
authorizeFlow();
try {
final FlowRegistry flowRegistry = flowRegistryClient.getFlowRegistry(id);
if (flowRegistry == null) {
throw new IllegalArgumentException("The specified registry id is unknown to this NiFi.");
}
final Set<Bucket> userBuckets = flowRegistry.getBuckets(NiFiUserUtils.getNiFiUser());
final Set<BucketEntity> buckets = serviceFacade.getBucketsForUser(id, NiFiUserUtils.getNiFiUser());
final BucketsEntity bucketsEntity = new BucketsEntity();
if (userBuckets != null) {
final Set<BucketEntity> bucketSet = new HashSet<>();
for (final Bucket userBucket : userBuckets) {
final BucketDTO bucket = new BucketDTO();
bucket.setId(userBucket.getIdentifier());
bucket.setName(userBucket.getName());
bucket.setDescription(userBucket.getDescription());
bucket.setCreated(userBucket.getCreatedTimestamp());
final BucketEntity bucketEntity = new BucketEntity();
bucketEntity.setBucket(bucket);
bucketSet.add(bucketEntity);
}
bucketsEntity.setBuckets(bucketSet);
}
bucketsEntity.setBuckets(buckets);
return generateOkResponse(bucketsEntity).build();
} catch (final IOException ioe) {
throw new NiFiCoreException("Unable to obtain bucket listing: " + ioe.getMessage(), ioe);
}
@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("registries/{registry-id}/buckets/{bucket-id}/flows")
@ApiOperation(value = "Gets the flows from the specified registry and bucket for the current user", response = BucketsEntity.class, authorizations = {
@Authorization(value = "Read - /flow")
})
@ApiResponses(value = {
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
@ApiResponse(code = 401, message = "Client could not be authenticated."),
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
@ApiResponse(code = 404, message = "The specified resource could not be found."),
@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 getFlows(
@ApiParam(
value = "The registry id.",
required = true
)
@PathParam("registry-id") String registryId,
@ApiParam(
value = "The bucket id.",
required = true
)
@PathParam("bucket-id") String bucketId) {
authorizeFlow();
final Set<VersionedFlowEntity> versionedFlows = serviceFacade.getFlowsForUser(registryId, bucketId, NiFiUserUtils.getNiFiUser());
final VersionedFlowsEntity versionedFlowsEntity = new VersionedFlowsEntity();
versionedFlowsEntity.setVersionedFlows(versionedFlows);
return generateOkResponse(versionedFlowsEntity).build();
}
@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("registries/{registry-id}/buckets/{bucket-id}/flows/{flow-id}/versions")
@ApiOperation(value = "Gets the flow versions from the specified registry and bucket for the specified flow for the current user", response = BucketsEntity.class, authorizations = {
@Authorization(value = "Read - /flow")
})
@ApiResponses(value = {
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
@ApiResponse(code = 401, message = "Client could not be authenticated."),
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
@ApiResponse(code = 404, message = "The specified resource could not be found."),
@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 getVersions(
@ApiParam(
value = "The registry id.",
required = true
)
@PathParam("registry-id") String registryId,
@ApiParam(
value = "The bucket id.",
required = true
)
@PathParam("bucket-id") String bucketId,
@ApiParam(
value = "The flow id.",
required = true
)
@PathParam("flow-id") String flowId) {
authorizeFlow();
final Set<VersionedFlowSnapshotMetadataEntity> versionedFlowSnapshotMetadataSet = serviceFacade.getFlowVersionsForUser(registryId, bucketId, flowId, NiFiUserUtils.getNiFiUser());
final VersionedFlowSnapshotMetadataSetEntity versionedFlowSnapshotMetadataSetEntity = new VersionedFlowSnapshotMetadataSetEntity();
versionedFlowSnapshotMetadataSetEntity.setVersionedFlowSnapshotMetadataSet(versionedFlowSnapshotMetadataSet);
return generateOkResponse(versionedFlowSnapshotMetadataSetEntity).build();
}
// --------------
@ -2629,10 +2669,6 @@ public class FlowResource extends ApplicationResource {
this.processGroupResource = processGroupResource;
}
public void setControllerResource(ControllerResource controllerResource) {
this.controllerResource = controllerResource;
}
public void setControllerServiceResource(ControllerServiceResource controllerServiceResource) {
this.controllerServiceResource = controllerServiceResource;
}
@ -2644,8 +2680,4 @@ public class FlowResource extends ApplicationResource {
public void setAuthorizer(Authorizer authorizer) {
this.authorizer = authorizer;
}
public void setFlowRegistryClient(FlowRegistryClient flowRegistryClient) {
this.flowRegistryClient = flowRegistryClient;
}
}

View File

@ -17,39 +17,12 @@
package org.apache.nifi.web.api;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.authorization.AuthorizableLookup;
import org.apache.nifi.authorization.Authorizer;
@ -58,6 +31,7 @@ import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.cluster.manager.NodeResponse;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.registry.flow.ComponentType;
@ -83,7 +57,7 @@ import org.apache.nifi.web.api.entity.AffectedComponentEntity;
import org.apache.nifi.web.api.entity.ProcessGroupEntity;
import org.apache.nifi.web.api.entity.VersionControlComponentMappingEntity;
import org.apache.nifi.web.api.entity.VersionControlInformationEntity;
import org.apache.nifi.web.api.entity.VersionedFlowEntity;
import org.apache.nifi.web.api.entity.StartVersionControlRequestEntity;
import org.apache.nifi.web.api.entity.VersionedFlowSnapshotEntity;
import org.apache.nifi.web.api.entity.VersionedFlowUpdateRequestEntity;
import org.apache.nifi.web.api.request.ClientIdParameter;
@ -96,12 +70,37 @@ import org.apache.nifi.web.util.Pause;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@Path("/versions")
@Api(value = "/versions", description = "Endpoint for managing version control for a flow")
@ -368,7 +367,7 @@ public class VersionsResource extends ApplicationResource {
})
public Response startVersionControl(
@ApiParam("The process group id.") @PathParam("id") final String groupId,
@ApiParam(value = "The versioned flow details.", required = true) final VersionedFlowEntity requestEntity) throws IOException {
@ApiParam(value = "The versioned flow details.", required = true) final StartVersionControlRequestEntity requestEntity) throws IOException {
// Verify the request
final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();
@ -390,6 +389,12 @@ public class VersionsResource extends ApplicationResource {
throw new IllegalArgumentException("The Registry ID must be supplied.");
}
// ensure we're not attempting to version the root group
final ProcessGroupEntity root = serviceFacade.getProcessGroup(FlowController.ROOT_GROUP_ID_ALIAS);
if (root.getId().equals(groupId)) {
throw new IllegalArgumentException("The Root Process Group cannot be versioned.");
}
if (isReplicateRequest()) {
// We first have to obtain a "lock" on all nodes in the cluster so that multiple Version Control requests
// are not being made simultaneously. We do this by making a POST to /nifi-api/versions/start-requests.
@ -688,6 +693,7 @@ public class VersionsResource extends ApplicationResource {
versionControlInfoDto.setBucketId(snapshotMetadata.getBucketIdentifier());
versionControlInfoDto.setCurrent(true);
versionControlInfoDto.setFlowId(snapshotMetadata.getFlowIdentifier());
versionControlInfoDto.setFlowName(snapshotMetadata.getFlowName());
versionControlInfoDto.setGroupId(groupId);
versionControlInfoDto.setModified(false);
versionControlInfoDto.setVersion(snapshotMetadata.getVersion());
@ -1139,12 +1145,13 @@ public class VersionsResource extends ApplicationResource {
updateRequestDto.setLastUpdated(new Date());
updateRequestDto.setProcessGroupId(groupId);
updateRequestDto.setRequestId(requestId);
updateRequestDto.setUri(generateResourceUri("versions", "update-requests", requestId));
updateRequestDto.setUri(generateResourceUri("versions", "revert-requests", requestId));
final VersionedFlowUpdateRequestEntity updateRequestEntity = new VersionedFlowUpdateRequestEntity();
updateRequestEntity.setProcessGroupRevision(revisionDto);
updateRequestEntity.setRequest(updateRequestDto);
request.markComplete(currentVersionEntity);
return generateOkResponse(updateRequestEntity).build();
}

View File

@ -16,7 +16,6 @@
*/
package org.apache.nifi.web.api.dto;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.action.Action;
@ -245,7 +244,6 @@ public final class DtoFactory {
dto.setSupportsManagedAuthorizer(AuthorizerCapabilityDetection.isManagedAuthorizer(authorizer));
dto.setSupportsConfigurableUsersAndGroups(AuthorizerCapabilityDetection.isConfigurableUserGroupProvider(authorizer));
dto.setSupportsConfigurableAuthorizer(AuthorizerCapabilityDetection.isConfigurableAccessPolicyProvider(authorizer));
dto.setSupportsFlowVersioning(CollectionUtils.isNotEmpty(flowRegistryClient.getRegistryIdentifiers()));
final Date now = new Date();
dto.setTimeOffset(TimeZone.getDefault().getOffset(now.getTime()));
@ -2191,6 +2189,8 @@ public final class DtoFactory {
dto.setRegistryId(versionControlInfo.getRegistryIdentifier());
dto.setBucketId(versionControlInfo.getBucketIdentifier());
dto.setFlowId(versionControlInfo.getFlowIdentifier());
// TODO - need to get flow name here
dto.setFlowName(group.getName());
dto.setVersion(versionControlInfo.getVersion());
dto.setCurrent(versionControlInfo.getCurrent().orElse(null));
dto.setModified(versionControlInfo.getModified().orElse(null));
@ -3409,6 +3409,7 @@ public final class DtoFactory {
copy.setRegistryId(original.getRegistryId());
copy.setBucketId(original.getBucketId());
copy.setFlowId(original.getFlowId());
copy.setFlowName(original.getFlowName());
copy.setVersion(original.getVersion());
copy.setCurrent(original.getCurrent());
copy.setModified(original.getModified());

View File

@ -158,6 +158,13 @@ public interface ProcessGroupDAO {
*/
void verifyDelete(String groupId);
/**
* Verifies the specified registry can be removed.
*
* @param registryId registry id
*/
void verifyDeleteFlowRegistry(String registryId);
/**
* Deletes the specified process group.
*

View File

@ -17,11 +17,15 @@
package org.apache.nifi.web.dao;
import java.util.Set;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.flow.FlowRegistry;
import org.apache.nifi.registry.flow.VersionedFlow;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
import org.apache.nifi.web.api.dto.RegistryDTO;
import java.util.Set;
public interface RegistryDAO {
FlowRegistry createFlowRegistry(RegistryDTO registryDto);
@ -30,6 +34,14 @@ public interface RegistryDAO {
Set<FlowRegistry> getFlowRegistries();
Set<FlowRegistry> getFlowRegistriesForUser(NiFiUser user);
Set<Bucket> getBucketsForUser(String registry, NiFiUser user);
Set<VersionedFlow> getFlowsForUser(String registryId, String bucketId, NiFiUser user);
Set<VersionedFlowSnapshotMetadata> getFlowVersionsForUser(String registryId, String bucketId, String flowId, NiFiUser user);
FlowRegistry removeFlowRegistry(String registryId);
}

View File

@ -17,15 +17,21 @@
package org.apache.nifi.web.dao.impl;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.flow.FlowRegistry;
import org.apache.nifi.registry.flow.FlowRegistryClient;
import org.apache.nifi.registry.flow.VersionedFlow;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
import org.apache.nifi.web.NiFiCoreException;
import org.apache.nifi.web.ResourceNotFoundException;
import org.apache.nifi.web.api.dto.RegistryDTO;
import org.apache.nifi.web.dao.RegistryDAO;
import java.io.IOException;
import java.util.Set;
import java.util.stream.Collectors;
public class FlowRegistryDAO implements RegistryDAO {
private FlowRegistryClient flowRegistryClient;
@ -51,6 +57,53 @@ public class FlowRegistryDAO implements RegistryDAO {
.collect(Collectors.toSet());
}
@Override
public Set<FlowRegistry> getFlowRegistriesForUser(final NiFiUser user) {
// TODO - implement to be user specific
return getFlowRegistries();
}
@Override
public Set<Bucket> getBucketsForUser(final String registryId, final NiFiUser user) {
try {
final FlowRegistry flowRegistry = flowRegistryClient.getFlowRegistry(registryId);
if (flowRegistry == null) {
throw new IllegalArgumentException("The specified registry id is unknown to this NiFi.");
}
return flowRegistry.getBuckets(user);
} catch (final IOException ioe) {
throw new NiFiCoreException("Unable to obtain bucket listing: " + ioe.getMessage(), ioe);
}
}
@Override
public Set<VersionedFlow> getFlowsForUser(String registryId, String bucketId, NiFiUser user) {
final Set<Bucket> bucketsForUser = getBucketsForUser(registryId, user);
// TODO - implement getBucket(bucketId, user)
final Bucket bucket = bucketsForUser.stream().filter(b -> b.getIdentifier().equals(bucketId)).findFirst().orElse(null);
if (bucket == null) {
throw new IllegalArgumentException("The specified bucket is not available.");
}
return bucket.getVersionedFlows();
}
@Override
public Set<VersionedFlowSnapshotMetadata> getFlowVersionsForUser(String registryId, String bucketId, String flowId, NiFiUser user) {
final Set<VersionedFlow> flowsForUser = getFlowsForUser(registryId, bucketId, user);
// TODO - implement getFlow(bucketId, flowId, user)
final VersionedFlow versionedFlow = flowsForUser.stream().filter(vf -> vf.getIdentifier().equals(flowId)).findFirst().orElse(null);
if (versionedFlow == null) {
throw new IllegalArgumentException("The specified flow is not available.");
}
return versionedFlow.getSnapshotMetadata();
}
@Override
public FlowRegistry removeFlowRegistry(final String registryId) {
final FlowRegistry registry = flowRegistryClient.removeFlowRegistry(registryId);

View File

@ -39,9 +39,11 @@ import org.apache.nifi.web.dao.ProcessGroupDAO;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGroupDAO {
@ -294,6 +296,26 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
group.verifyCanDelete();
}
@Override
public void verifyDeleteFlowRegistry(String registryId) {
final ProcessGroup rootGroup = flowController.getRootGroup();
final VersionControlInformation versionControlInformation = rootGroup.getVersionControlInformation();
if (versionControlInformation != null && versionControlInformation.getRegistryIdentifier().equals(registryId)) {
throw new IllegalStateException("The Registry cannot be removed because a Process Group currently under version control is tracking to it.");
}
final Set<VersionControlInformation> trackedVersionControlInformation = rootGroup.findAllProcessGroups().stream()
.map(group -> group.getVersionControlInformation())
.filter(Objects::nonNull)
.filter(vci -> vci.getRegistryIdentifier().equals(registryId))
.collect(Collectors.toSet());
if (!trackedVersionControlInformation.isEmpty()) {
throw new IllegalStateException("The Registry cannot be removed because a Process Group currently under version control is tracking to it.");
}
}
@Override
public void deleteProcessGroup(String processGroupId) {
// get the group

View File

@ -213,7 +213,6 @@
<property name="remoteProcessGroupResource" ref="remoteProcessGroupResource"/>
<property name="connectionResource" ref="connectionResource"/>
<property name="templateResource" ref="templateResource"/>
<property name="controllerResource" ref="controllerResource"/>
<property name="controllerServiceResource" ref="controllerServiceResource"/>
<property name="reportingTaskResource" ref="reportingTaskResource"/>
<property name="processGroupResource" ref="processGroupResource"/>
@ -221,7 +220,6 @@
<property name="clusterCoordinator" ref="clusterCoordinator"/>
<property name="requestReplicator" ref="requestReplicator" />
<property name="flowController" ref="flowController" />
<property name="flowRegistryClient" ref="flowRegistryClient" />
</bean>
<bean id="resourceResource" class="org.apache.nifi.web.api.ResourceResource" scope="singleton">
<property name="serviceFacade" ref="serviceFacade"/>

View File

@ -116,6 +116,7 @@
<jsp:include page="/WEB-INF/partials/canvas/fill-color-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/connections-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/save-flow-version-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/import-flow-version-dialog.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/registry-configuration-dialog.jsp"/>
<div id="canvas-container" class="unselectable"></div>
<div id="canvas-tooltips">

View File

@ -0,0 +1,44 @@
<%--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--%>
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
<div id="import-flow-version-dialog" layout="column" class="hidden large-dialog">
<div class="dialog-content">
<div class="setting">
<div class="setting-name">Registry</div>
<div class="setting-field">
<div id="import-flow-version-registry-combo"></div>
<div id="import-flow-version-registry" class="hidden"></div>
</div>
</div>
<div class="setting">
<div class="setting-name">Location</div>
<div class="setting-field">
<div id="import-flow-version-bucket-combo"></div>
<div id="import-flow-version-bucket" class="hidden"></div>
</div>
</div>
<div class="setting">
<div class="setting-name">Name</div>
<div class="setting-field">
<span id="import-flow-version-process-group-id" class="hidden"></span>
<div id="import-flow-version-name-combo"></div>
<div id="import-flow-version-name" class="hidden"></div>
</div>
</div>
<div id="import-flow-version-table"></div>
</div>
</div>

View File

@ -128,13 +128,13 @@
<div class="button-spacer-large">&nbsp;</div>
<div id="operate-template" class="action-button" title="Create Template">
<button ng-click="appCtrl.nf.Actions['template'](appCtrl.nf.CanvasUtils.getSelection());"
ng-disabled="!(appCtrl.nf.CanvasUtils.canWrite() && (appCtrl.nf.CanvasUtils.getSelection().empty() || appCtrl.nf.CanvasUtils.canRead(appCtrl.nf.CanvasUtils.getSelection())));">
ng-disabled="!(appCtrl.nf.CanvasUtils.canWriteCurrentGroup() && (appCtrl.nf.CanvasUtils.getSelection().empty() || appCtrl.nf.CanvasUtils.canRead(appCtrl.nf.CanvasUtils.getSelection())));">
<div class="graph-control-action-icon icon icon-template-save"></div></button>
</div>
<div class="button-spacer-small">&nbsp;</div>
<div id="operate-template-upload" class="action-button" title="Upload Template">
<button ng-click="appCtrl.nf.Actions['uploadTemplate']();"
ng-disabled="!(appCtrl.nf.CanvasUtils.canWrite() && appCtrl.nf.CanvasUtils.getSelection().empty());">
ng-disabled="!(appCtrl.nf.CanvasUtils.canWriteCurrentGroup() && appCtrl.nf.CanvasUtils.getSelection().empty());">
<div class="graph-control-action-icon icon icon-template-import"></div></button>
</div>
<div class="clear"></div>

View File

@ -23,5 +23,8 @@
<input id="new-process-group-name" type="text"/>
</div>
</div>
<div class="setting">
<span id="import-process-group-link" class="link"><i class="fa fa-cloud-download" aria-hidden="true" style="margin-left: 5px; margin-right: 5px;"></i>Import version...</span>
</div>
</div>
</div>

View File

@ -22,7 +22,7 @@
<div class="fa fa-question-circle" alt="Info" title="Specify the remote target NiFi URLs. Multiple URLs can be specified in comma-separated format. Different protocols cannot be mixed. If remote NiFi is a cluster, two or more node URLs are recommended for better connection establishment availability."></div>
</div>
<div class="setting-field">
<input id="new-remote-process-group-uris" type="text" placeholder="https://remotehost:8080/nifi"/>
<input id="new-remote-process-group-uris" type="text" placeholder="https://remotehost:8443/nifi"/>
</div>
</div>
<div class="setting">

View File

@ -25,9 +25,9 @@
</div>
</div>
<div class="setting">
<div class="setting-name">Location</div>
<div class="setting-name">URL</div>
<div class="setting-field">
<input type="text" id="registry-location" class="setting-input"/>
<input type="text" id="registry-location" class="setting-input" placeholder="https://remotehost:8443"/>
</div>
</div>
<div class="setting">

View File

@ -20,34 +20,36 @@
<div class="setting">
<div class="setting-name">Registry</div>
<div class="setting-field">
<div id="flow-version-registry-combo"></div>
<div id="flow-version-registry" class="hidden"></div>
<div id="save-flow-version-registry-combo" class="hidden"></div>
<div id="save-flow-version-registry" class="hidden"></div>
</div>
</div>
<div class="setting">
<div class="setting-name">Location</div>
<div class="setting-field">
<div id="flow-version-bucket-combo"></div>
<div id="flow-version-bucket" class="hidden"></div>
<div id="save-flow-version-bucket-combo" class="hidden"></div>
<div id="save-flow-version-bucket" class="hidden"></div>
</div>
</div>
<div class="setting">
<div class="setting-name">Name</div>
<div class="setting-field">
<span id="flow-version-process-group-id" class="hidden"></span>
<input type="text" id="flow-version-name" class="setting-input"/>
<span id="save-flow-version-process-group-id" class="hidden"></span>
<input type="text" id="save-flow-version-name-field" class="setting-input hidden"/>
<div id="save-flow-version-name" class="hidden"></div>
</div>
</div>
<div class="setting">
<div class="setting-name">Description</div>
<div class="setting-field">
<textarea id="flow-version-description" class="setting-input"></textarea>
<textarea id="save-flow-version-description-field" class="setting-input hidden"></textarea>
<div id="save-flow-version-description" class="hidden"></div>
</div>
</div>
<div class="setting">
<div class="setting-name">Change Comments</div>
<div class="setting-name">Comments</div>
<div class="setting-field">
<textarea id="flow-version-change-comments" class="setting-input"></textarea>
<textarea id="save-flow-version-change-comments" class="setting-input"></textarea>
</div>
</div>
</div>

View File

@ -213,13 +213,27 @@ div.progress-label {
}
/*
Flow Version
Save Flow Version
*/
#flow-version-description, #flow-version-change-comments {
#save-flow-version-description-field, #save-flow-version-change-comments {
height: 85px;
}
/*
Import Flow Version
*/
#import-flow-version-table {
overflow: hidden;
position: absolute;
top: 202px;
left: 0px;
right: 0px;
bottom: 0px;
height: 225px;
}
/*
Variable Registry
*/

View File

@ -24,9 +24,10 @@
'nf.Birdseye',
'nf.Graph',
'nf.CanvasUtils',
'nf.ErrorHandler'],
function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler) {
return (nf.ng.GroupComponent = factory($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler));
'nf.ErrorHandler',
'nf.Common'],
function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon) {
return (nf.ng.GroupComponent = factory($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.ng.GroupComponent =
@ -35,16 +36,18 @@
require('nf.Birdseye'),
require('nf.Graph'),
require('nf.CanvasUtils'),
require('nf.ErrorHandler')));
require('nf.ErrorHandler'),
require('nf.Common')));
} else {
nf.ng.GroupComponent = factory(root.$,
root.nf.Client,
root.nf.Birdseye,
root.nf.Graph,
root.nf.CanvasUtils,
root.nf.ErrorHandler);
root.nf.ErrorHandler,
root.nf.Common);
}
}(this, function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler) {
}(this, function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfCommon) {
'use strict';
return function (serviceProvider) {
@ -126,6 +129,7 @@
handler: {
close: function () {
$('#new-process-group-name').val('');
$('#new-process-group-dialog').removeData('pt');
}
}
});
@ -145,9 +149,24 @@
* Show the modal.
*/
show: function () {
if (nfCommon.canVersionFlows()) {
$('#import-process-group-link').show();
} else {
$('#import-process-group-link').hide();
}
this.getElement().modal('show');
},
/**
* Stores the pt.
*
* @param pt
*/
storePt: function (pt) {
$('#new-process-group-dialog').data('pt', pt);
},
/**
* Hide the modal.
*/
@ -255,6 +274,7 @@
}]);
// show the dialog
groupComponent.modal.storePt(pt);
groupComponent.modal.show();
// set up the focus and key handlers

View File

@ -1254,14 +1254,14 @@
},
/**
* Reverts outstanding changes.
* Reverts local changes.
*/
revertFlowChanges: function (selection) {
revertLocalChanges: function (selection) {
if (selection.empty()) {
nfFlowVersion.revertFlowChanges(nfCanvasUtils.getGroupId());
nfFlowVersion.revertLocalChanges(nfCanvasUtils.getGroupId());
} else if (selection.size() === 1) {
var selectionData = selection.datum();
nfFlowVersion.revertFlowChanges(selectionData.id);
nfFlowVersion.revertLocalChanges(selectionData.id);
}
},
@ -1269,18 +1269,25 @@
* Changes the flow version.
*/
changeFlowVersion: function (selection) {
if (selection.empty()) {
nfFlowVersion.showChangeFlowVersionDialog(nfCanvasUtils.getGroupId());
} else if (selection.size() === 1) {
var selectionData = selection.datum();
if (nfCanvasUtils.isProcessGroup(selection)) {
nfFlowVersion.showChangeFlowVersionDialog(selectionData.id);
}
}
},
/**
* Disconnects a Process Group from flow versioning.
*/
disconnectFlowVersioning: function (selection) {
stopVersionControl: function (selection) {
if (selection.empty()) {
nfFlowVersion.disconnectFlowVersioning(nfCanvasUtils.getGroupId());
nfFlowVersion.stopVersionControl(nfCanvasUtils.getGroupId());
} else if (selection.size() === 1) {
var selectionData = selection.datum();
nfFlowVersion.disconnectFlowVersioning(selectionData.id);
nfFlowVersion.stopVersionControl(selectionData.id);
}
},

View File

@ -337,7 +337,6 @@
nfCanvas.setManagedAuthorizer(configDetails.supportsManagedAuthorizer);
nfCanvas.setConfigurableAuthorizer(configDetails.supportsConfigurableAuthorizer);
nfCanvas.setConfigurableUsersAndGroups(configDetails.supportsConfigurableUsersAndGroups);
nfCanvas.setSupportsFlowVersioning(configDetails.supportsFlowVersioning);
// init nfStorage
nfStorage.init();
@ -356,7 +355,7 @@
nfQueueListing.init();
nfVariableRegistry.init();
nfComponentState.init();
nfFlowVersion.init();
nfFlowVersion.init(configDetails.timeOffset);
nfComponentVersion.init(nfSettings);
// initialize the component behaviors

View File

@ -1819,13 +1819,6 @@
}
},
/**
* Returns whether this NiFi supports flow versioning.
*/
supportsFlowVersioning: function () {
return nfCanvas.supportsFlowVersioning();
},
/**
* Returns whether the authorizer is managed.
*/

View File

@ -85,7 +85,6 @@
var permissions = null;
var parentGroupId = null;
var managedAuthorizer = false;
var supportsFlowVersioning = false;
var configurableAuthorizer = false;
var configurableUsersAndGroups = false;
var svg = null;
@ -909,23 +908,6 @@
return managedAuthorizer;
},
/**
* Set whether this NiFi supports flow versioning.
*
* @param bool Whether this NiFi supports flow versioning
*/
setSupportsFlowVersioning: function (bool) {
supportsFlowVersioning = bool;
},
/**
*
* @returns {boolean}
*/
supportsFlowVersioning: function () {
return supportsFlowVersioning;
},
/**
* Set whether the authorizer is configurable.
*

View File

@ -375,11 +375,17 @@
* @param selection
*/
var supportsFlowVersioning = function (selection) {
if (nfCanvasUtils.supportsFlowVersioning() === false) {
if (nfCommon.canVersionFlows() === false) {
return false;
}
if (selection.empty()) {
// prevent versioning of the root group
if (nfCanvasUtils.getParentGroupId() === null) {
return false;
}
// if not root group, ensure adequate permissions
return nfCanvasUtils.canReadCurrentGroup() && nfCanvasUtils.canWriteCurrentGroup();
}
@ -632,13 +638,13 @@
{id: 'variable-registry-menu-item', condition: hasVariables, menuItem: {clazz: 'fa', text: 'Variables', action: 'openVariableRegistry'}},
{separator: true},
{id: 'version-menu-item', groupMenuItem: {clazz: 'fa', text: 'Version'}, menuItems: [
{id: 'start-version-control-menu-item', condition: supportsStartFlowVersioning, menuItem: {clazz: 'fa fa-floppy-o', text: 'Start version control', action: 'saveFlowVersion'}},
{id: 'start-version-control-menu-item', condition: supportsStartFlowVersioning, menuItem: {clazz: 'fa fa-upload', text: 'Start version control', action: 'saveFlowVersion'}},
{separator: true},
{id: 'commit-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa fa-floppy-o', text: 'Commit local changes', action: 'saveFlowVersion'}},
{id: 'revert-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Revert local changes', action: 'revertFlowChanges'}},
{id: 'commit-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa fa-upload', text: 'Commit local changes', action: 'saveFlowVersion'}},
{id: 'revert-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa fa-undo', text: 'Revert local changes', action: 'revertLocalChanges'}},
{id: 'change-version-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Change version', action: 'changeFlowVersion'}},
{separator: true},
{id: 'stop-version-control-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Stop version control', action: 'disconnectFlowVersioning'}}
{id: 'stop-version-control-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Stop version control', action: 'stopVersionControl'}}
]},
{separator: true},
{id: 'enter-group-menu-item', condition: isProcessGroup, menuItem: {clazz: 'fa fa-sign-in', text: 'Enter group', action: 'enterGroup'}},

View File

@ -82,8 +82,7 @@
reportingTaskTypes: '../nifi-api/flow/reporting-task-types',
createReportingTask: '../nifi-api/controller/reporting-tasks',
reportingTasks: '../nifi-api/flow/reporting-tasks',
createRegistry: '../nifi-api/controller/registries',
registries: '../nifi-api/flow/registries'
registries: '../nifi-api/controller/registry-clients'
}
};
@ -486,7 +485,7 @@
// add the new registry
var addRegistry = $.ajax({
type: 'POST',
url: config.urls.createRegistry,
url: config.urls.registries,
data: JSON.stringify(registryEntity),
dataType: 'json',
contentType: 'application/json'
@ -877,7 +876,6 @@
// initialize the registry configuration dialog
$('#registry-configuration-dialog').modal({
scrollableContentStyle: 'scrollable',
headerText: 'Add Registry',
handler: {
close: function () {
$('#registry-id').text('');
@ -1351,7 +1349,7 @@
$('#registry-description').val(registryEntity.component.description);
// show the dialog
$('#registry-configuration-dialog').modal('setButtonModel', [{
$('#registry-configuration-dialog').modal('setHeaderText', 'Edit Registry Client').modal('setButtonModel', [{
buttonText: 'Update',
color: {
base: '#728E9B',
@ -1597,7 +1595,7 @@
name: 'Reporting Tasks',
tabContentId: 'reporting-tasks-tab-content'
}, {
name: 'Registries',
name: 'Registry Clients',
tabContentId: 'registries-tab-content'
}],
select: function () {
@ -1625,9 +1623,9 @@
} else if (tab === 'Reporting Tasks') {
$('#settings-save').hide();
return 'Create a new reporting task';
} else if (tab === 'Registries') {
} else if (tab === 'Registry Clients') {
$('#settings-save').hide();
return 'Register a new registry';
return 'Register a new registry client';
}
});
} else {
@ -1637,7 +1635,7 @@
if (tab === 'Reporting Task Controller Services') {
$('#controller-cs-availability').show();
} else if (tab === 'Reporting Tasks' || tab === 'Registries') {
} else if (tab === 'Reporting Tasks' || tab === 'Registry Clients') {
$('#controller-cs-availability').hide();
}
@ -1676,8 +1674,8 @@
// set the initial focus
$('#reporting-task-type-filter').focus();
} else if (selectedTab === 'Registries') {
$('#registry-configuration-dialog').modal('setButtonModel', [{
} else if (selectedTab === 'Registry Clients') {
$('#registry-configuration-dialog').modal('setHeaderText', 'Add Registry Client').modal('setButtonModel', [{
buttonText: 'Add',
color: {
base: '#728E9B',
@ -1702,6 +1700,9 @@
}
}
}]).modal('show');
// set the initial focus
$('#registry-name').focus();
}
});

View File

@ -556,6 +556,17 @@
return null;
},
/**
* Determines whether the current user can version flows.
*/
canVersionFlows: function () {
if (nfCommon.isDefinedAndNotNull(nfCommon.currentUser)) {
return nfCommon.currentUser.canVersionFlows === true;
} else {
return false;
}
},
/**
* Determines whether the current user can access provenance.
*