NIFI-2501: - Ensuring users can access the controller service list regardless of permissions on the corresponding process group or controller. - Better handling the case where the user had write permissions but no read permissions. - Returning to the appropriate controller service listing after going to the usage page.

This closes #835

Signed-off-by: jpercivall <joepercivall@yahoo.com>
This commit is contained in:
Matt Gilman 2016-08-10 14:52:59 -04:00 committed by jpercivall
parent 51c566ffc8
commit d45114e48d
14 changed files with 79 additions and 96 deletions

View File

@ -20,11 +20,8 @@ import com.wordnik.swagger.annotations.ApiModelProperty;
import org.apache.nifi.web.api.dto.ControllerConfigurationDTO;
import org.apache.nifi.web.api.dto.PermissionsDTO;
import org.apache.nifi.web.api.dto.RevisionDTO;
import org.apache.nifi.web.api.dto.util.TimeAdapter;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Date;
/**
* 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 ControllerConfigurationDTO.
@ -32,7 +29,6 @@ import java.util.Date;
@XmlRootElement(name = "controllerConfigurationEntity")
public class ControllerConfigurationEntity extends Entity implements Permissible<ControllerConfigurationDTO> {
private Date currentTime;
private ControllerConfigurationDTO controllerConfiguration;
private RevisionDTO revision;
private PermissionsDTO permissions;
@ -87,18 +83,4 @@ public class ControllerConfigurationEntity extends Entity implements Permissible
this.permissions = permissions;
}
/**
* @return current time on the server
*/
@XmlJavaTypeAdapter(TimeAdapter.class)
@ApiModelProperty(
value = "The current time on the system."
)
public Date getCurrentTime() {
return currentTime;
}
public void setCurrentTime(Date currentTime) {
this.currentTime = currentTime;
}
}

View File

@ -16,7 +16,12 @@
*/
package org.apache.nifi.web.api.entity;
import com.wordnik.swagger.annotations.ApiModelProperty;
import org.apache.nifi.web.api.dto.util.TimeAdapter;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Date;
import java.util.Set;
/**
@ -25,6 +30,7 @@ import java.util.Set;
@XmlRootElement(name = "controllerServicesEntity")
public class ControllerServicesEntity extends Entity {
private Date currentTime;
private Set<ControllerServiceEntity> controllerServices;
/**
@ -38,4 +44,19 @@ public class ControllerServicesEntity extends Entity {
this.controllerServices = controllerServices;
}
/**
* @return current time on the server
*/
@XmlJavaTypeAdapter(TimeAdapter.class)
@ApiModelProperty(
value = "The current time on the system."
)
public Date getCurrentTime() {
return currentTime;
}
public void setCurrentTime(Date currentTime) {
this.currentTime = currentTime;
}
}

View File

@ -19,11 +19,8 @@ package org.apache.nifi.web.api.entity;
import com.wordnik.swagger.annotations.ApiModelProperty;
import org.apache.nifi.web.api.dto.ProcessGroupDTO;
import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO;
import org.apache.nifi.web.api.dto.util.TimeAdapter;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Date;
/**
* 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 ProcessGroupDTO.
@ -34,7 +31,6 @@ public class ProcessGroupEntity extends ComponentEntity implements Permissible<P
private ProcessGroupDTO component;
private ProcessGroupStatusDTO status;
private Date currentTime;
private Integer runningCount;
private Integer stoppedCount;
private Integer invalidCount;
@ -184,18 +180,4 @@ public class ProcessGroupEntity extends ComponentEntity implements Permissible<P
this.inactiveRemotePortCount = inactiveRemotePortCount;
}
/**
* @return current time on the server
*/
@XmlJavaTypeAdapter(TimeAdapter.class)
@ApiModelProperty(
value = "The current time on the system."
)
public Date getCurrentTime() {
return currentTime;
}
public void setCurrentTime(Date currentTime) {
this.currentTime = currentTime;
}
}

View File

@ -417,6 +417,7 @@ public class FlowResource extends ApplicationResource {
// create the response entity
final ControllerServicesEntity entity = new ControllerServicesEntity();
entity.setCurrentTime(new Date());
entity.setControllerServices(controllerServices);
// generate the response
@ -467,6 +468,7 @@ public class FlowResource extends ApplicationResource {
// create the response entity
final ControllerServicesEntity entity = new ControllerServicesEntity();
entity.setCurrentTime(new Date());
entity.setControllerServices(controllerServices);
// generate the response

View File

@ -152,7 +152,6 @@ public final class EntityFactory {
public ControllerConfigurationEntity createControllerConfigurationEntity(final ControllerConfigurationDTO dto, final RevisionDTO revision, final PermissionsDTO permissions) {
final ControllerConfigurationEntity entity = new ControllerConfigurationEntity();
entity.setRevision(revision);
entity.setCurrentTime(new Date());
if (dto != null) {
entity.setPermissions(permissions);
if (permissions != null && permissions.getCanRead()) {
@ -209,7 +208,6 @@ public final class EntityFactory {
final ProcessGroupStatusDTO status, final List<BulletinDTO> bulletins) {
final ProcessGroupEntity entity = new ProcessGroupEntity();
entity.setRevision(revision);
entity.setCurrentTime(new Date());
if (dto != null) {
entity.setPermissions(permissions);
entity.setStatus(status);

View File

@ -127,7 +127,6 @@
<jsp:include page="/WEB-INF/partials/processor-details.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/process-group-configuration.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/policy-management.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/process-group-details.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/remote-process-group-configuration.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/remote-process-group-details.jsp"/>
<jsp:include page="/WEB-INF/partials/canvas/remote-process-group-ports.jsp"/>

View File

@ -128,8 +128,7 @@
<md-menu-divider></md-menu-divider>
<md-menu-item layout-align="space-around center">
<a id="flow-settings-link"
ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.controllerSettings.shell.launch();"
ng-class="{disabled: !appCtrl.nf.Common.canAccessController()}">
ng-click="appCtrl.serviceProvider.headerCtrl.globalMenuCtrl.controllerSettings.shell.launch();">
<i class="fa fa-wrench"></i>Controller Settings
</a>
</md-menu-item>

View File

@ -1,39 +0,0 @@
<%--
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="process-group-details" class="hidden medium-dialog">
<div class="dialog-content">
<div class="setting">
<div class="setting-name">Name</div>
<div class="setting-field">
<span id="read-only-process-group-name"></span>
</div>
</div>
<div class="setting">
<div class="setting-name">Id</div>
<div class="setting-field">
<span id="read-only-process-group-id"></span>
</div>
</div>
<div class="setting">
<div class="setting-name">Comments</div>
<div class="setting-field">
<div id="read-only-process-group-comments"></div>
</div>
</div>
</div>
</div>

View File

@ -123,11 +123,9 @@ nf.ng.Canvas.GlobalMenuCtrl = function (serviceProvider) {
* Launch the settings shell.
*/
launch: function () {
if (nf.Common.canAccessController()) {
nf.Settings.showSettings();
}
}
}
};
/**

View File

@ -294,7 +294,7 @@ nf.ng.Canvas.GraphControlsCtrl = function (serviceProvider, navigateCtrl, operat
var selection = nf.CanvasUtils.getSelection();
if (selection.empty()) {
return nf.Canvas.canRead() || nf.Canvas.canWrite();
return true;
}
return nf.CanvasUtils.isConfigurable(selection) || nf.CanvasUtils.hasDetails(selection);

View File

@ -936,6 +936,10 @@ nf.CanvasUtils = (function () {
if (selection.size() !== 1) {
return false;
}
if (nf.CanvasUtils.isProcessGroup(selection)) {
return true;
}
if (nf.CanvasUtils.canRead(selection) === false || nf.CanvasUtils.canModify(selection) === false) {
return false;
}
@ -956,16 +960,19 @@ nf.CanvasUtils = (function () {
if (selection.size() !== 1) {
return false;
}
if (nf.CanvasUtils.isProcessGroup(selection)) {
return true;
}
if (nf.CanvasUtils.canRead(selection) === false) {
return false;
}
if (nf.CanvasUtils.canModify(selection)) {
if (nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isInputPort(selection) || nf.CanvasUtils.isOutputPort(selection) || nf.CanvasUtils.isRemoteProcessGroup(selection) || nf.CanvasUtils.isConnection(selection)) {
return !nf.CanvasUtils.isConfigurable(selection);
}
} else {
return nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isConnection(selection) || nf.CanvasUtils.isProcessGroup(selection) || nf.CanvasUtils.isInputPort(selection) || nf.CanvasUtils.isOutputPort(selection) || nf.CanvasUtils.isRemoteProcessGroup(selection);
return nf.CanvasUtils.isProcessor(selection) || nf.CanvasUtils.isConnection(selection) || nf.CanvasUtils.isInputPort(selection) || nf.CanvasUtils.isOutputPort(selection) || nf.CanvasUtils.isRemoteProcessGroup(selection);
}
return false;

View File

@ -668,7 +668,20 @@ nf.ControllerServices = (function () {
nf.Shell.showPage('../nifi-docs/documentation?' + $.param({
select: nf.Common.substringAfterLast(controllerServiceEntity.component.type, '.')
})).done(function() {
if (nf.Common.isDefinedAndNotNull(controllerServiceEntity.component.parentGroupId)) {
var groupId;
var processGroup = nf.ProcessGroup.get(controllerServiceEntity.component.parentGroupId);
if (nf.Common.isDefinedAndNotNull(processGroup)) {
groupId = processGroup.id;
} else {
groupId = nf.Canvas.getGroupId();
}
// reload the corresponding group
nf.ProcessGroupConfiguration.showConfiguration(groupId);
} else {
nf.Settings.showSettings();
}
});
}
}

View File

@ -122,9 +122,6 @@ nf.ProcessGroupConfiguration = (function () {
// store the process group
$('#process-group-configuration').data('process-group', response);
// update the current time
$('#process-group-configuration-last-refreshed').text(response.currentTime);
if (response.permissions.canWrite) {
var processGroup = response.component;
@ -153,6 +150,17 @@ nf.ProcessGroupConfiguration = (function () {
deferred.resolve();
}).fail(function (xhr, status, error) {
if (xhr.status === 403) {
if (groupId === nf.Canvas.getGroupId()) {
$('#process-group-configuration').data('process-group', {
'permissions': {
canRead: false,
canWrite: nf.Canvas.canWrite()
}
});
} else {
$('#process-group-configuration').data('process-group', nf.ProcessGroup.get(groupId));
}
setUnauthorizedText();
setEditable(false);
deferred.resolve();
@ -167,7 +175,12 @@ nf.ProcessGroupConfiguration = (function () {
var controllerServices = nf.ControllerServices.loadControllerServices(controllerServicesUri, getControllerServicesTable());
// wait for everything to complete
return $.when(processGroup, controllerServices).fail(nf.Common.handleAjaxError);
return $.when(processGroup, controllerServices).done(function (processGroupResult, controllerServicesResult) {
var controllerServicesResponse = controllerServicesResult[0];
// update the current time
$('#process-group-configuration-last-refreshed').text(controllerServicesResponse.currentTime);
}).fail(nf.Common.handleAjaxError);
};
/**

View File

@ -855,9 +855,6 @@ nf.Settings = (function () {
url: config.urls.controllerConfig,
dataType: 'json'
}).done(function (response) {
// update the current time
$('#settings-last-refreshed').text(response.currentTime);
if (response.permissions.canWrite) {
// populate the settings
$('#maximum-timer-driven-thread-count-field').removeClass('unset').val(response.component.maxTimerDrivenThreadCount);
@ -900,7 +897,12 @@ nf.Settings = (function () {
var reportingTasks = loadReportingTasks();
// return a deferred for all parts of the settings
return $.when(settings, controllerServices, reportingTasks).fail(nf.Common.handleAjaxError);
return $.when(settings, controllerServices, reportingTasks).done(function (settingsResult, controllerServicesResult) {
var controllerServicesResponse = controllerServicesResult[0];
// update the current time
$('#settings-last-refreshed').text(controllerServicesResponse.currentTime);
}).fail(nf.Common.handleAjaxError);
};
/**
@ -983,7 +985,13 @@ nf.Settings = (function () {
$('#new-service-or-task').hide();
$('#settings-save').show();
} else {
if (nf.Common.canModifyController()) {
var canModifyController = false;
if (nf.Common.isDefinedAndNotNull(nf.Common.currentUser)) {
// only consider write permissions for creating new controller services/reporting tasks
canModifyController = nf.Common.currentUser.controllerPermissions.canWrite === true;
}
if (canModifyController) {
$('#new-service-or-task').show();
$('div.controller-settings-table').css('top', '32px');