mirror of https://github.com/portainer/portainer
refactor(UAC): refactor common views to components (#1013)
parent
344eee098d
commit
a864641692
|
@ -20,8 +20,6 @@ angular.module('portainer', [
|
|||
'portainer.services',
|
||||
'auth',
|
||||
'dashboard',
|
||||
'common.accesscontrol.panel',
|
||||
'common.accesscontrol.form',
|
||||
'container',
|
||||
'containerConsole',
|
||||
'containerLogs',
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
<div ng-controller="AccessControlFormController">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Access control
|
||||
</div>
|
||||
<!-- access-control-switch -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="ownership" class="control-label text-left">
|
||||
Enable access control
|
||||
<portainer-tooltip position="bottom" message="When enabled, you can restrict the access and management of this resource."></portainer-tooltip>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input name="ownership" type="checkbox" ng-model="formValues.enableAccessControl" ng-click="synchronizeFormData()"><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !access-control-switch -->
|
||||
<!-- restricted-access -->
|
||||
<div class="form-group" ng-if="formValues.enableAccessControl" style="margin-bottom: 0">
|
||||
<div class="boxselector_wrapper">
|
||||
<div ng-if="isAdmin">
|
||||
<input type="radio" id="access_administrators" ng-model="formValues.Ownership" ng-click="synchronizeFormData()" value="administrators">
|
||||
<label for="access_administrators">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'administrators' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Administrators
|
||||
</div>
|
||||
<p>I want to restrict the management of this resource to administrators only</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="isAdmin">
|
||||
<input type="radio" id="access_restricted" ng-model="formValues.Ownership" ng-click="synchronizeFormData()" value="restricted">
|
||||
<label for="access_restricted">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'restricted' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Restricted
|
||||
</div>
|
||||
<p>
|
||||
I want to restrict the management of this resource to a set of users and/or teams
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="!isAdmin">
|
||||
<input type="radio" id="access_private" ng-model="formValues.Ownership" ng-click="synchronizeFormData()" value="private">
|
||||
<label for="access_private">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'private' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Private
|
||||
</div>
|
||||
<p>
|
||||
I want to this resource to be manageable by myself only
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="!isAdmin && availableTeams.length > 0">
|
||||
<input type="radio" id="access_restricted" ng-model="formValues.Ownership" ng-click="synchronizeFormData()" value="restricted">
|
||||
<label for="access_restricted">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'restricted' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Restricted
|
||||
</div>
|
||||
<p ng-if="availableTeams.length === 1">
|
||||
I want any member of my team (<b>{{ availableTeams[0].Name }}</b>) to be able to manage this resource
|
||||
</p>
|
||||
<p ng-if="availableTeams.length > 1">
|
||||
I want to restrict the management of this resource to one or more of my teams
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- restricted-access -->
|
||||
<!-- authorized-teams -->
|
||||
<div class="form-group" ng-if="formValues.enableAccessControl && formValues.Ownership === 'restricted' && (isAdmin || (!isAdmin && availableTeams.length > 1))" >
|
||||
<div class="col-sm-12">
|
||||
<label for="group-access" class="control-label text-left">
|
||||
Authorized teams
|
||||
<portainer-tooltip ng-if="isAdmin && availableTeams.length > 0" position="bottom" message="You can select which teams(s) will be able to manage this resource."></portainer-tooltip>
|
||||
<portainer-tooltip ng-if="!isAdmin && availableTeams.length > 1" position="bottom" message="As you are a member of multiple teams, you can select which teams(s) will be able to manage this resource."></portainer-tooltip>
|
||||
</label>
|
||||
<span ng-if="isAdmin && availableTeams.length === 0" class="small text-muted" style="margin-left: 20px;">
|
||||
You have not yet created any team. Head over the <a ui-sref="teams">teams view</a> to manage user teams.
|
||||
</span>
|
||||
<span isteven-multi-select
|
||||
ng-if="(isAdmin && availableTeams.length > 0) || (!isAdmin && availableTeams.length > 1)"
|
||||
input-model="availableTeams"
|
||||
output-model="formValues.Ownership_Teams"
|
||||
button-label="Name"
|
||||
item-label="Name"
|
||||
tick-property="ticked"
|
||||
helper-elements="filter"
|
||||
search-property="Name"
|
||||
on-item-click="synchronizeFormData()"
|
||||
translation="{nothingSelected: 'Select one or more teams', search: 'Search...'}"
|
||||
style="margin-left: 20px;">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !authorized-teams -->
|
||||
<!-- authorized-users -->
|
||||
<div class="form-group" ng-if="formValues.enableAccessControl && formValues.Ownership === 'restricted' && isAdmin">
|
||||
<div class="col-sm-12">
|
||||
<label for="group-access" class="control-label text-left">
|
||||
Authorized users
|
||||
<portainer-tooltip ng-if="isAdmin && availableUsers.length > 0" position="bottom" message="You can select which user(s) will be able to manage this resource."></portainer-tooltip>
|
||||
</label>
|
||||
<span ng-if="availableUsers.length === 0" class="small text-muted" style="margin-left: 20px;">
|
||||
You have not yet created any user. Head over the <a ui-sref="users">users view</a> to manage users.
|
||||
</span>
|
||||
<span isteven-multi-select
|
||||
ng-if="availableUsers.length > 0"
|
||||
input-model="availableUsers"
|
||||
output-model="formValues.Ownership_Users"
|
||||
button-label="Username"
|
||||
item-label="Username"
|
||||
tick-property="ticked"
|
||||
helper-elements="filter"
|
||||
search-property="Username"
|
||||
on-item-click="synchronizeFormData()"
|
||||
translation="{nothingSelected: 'Select one or more users', search: 'Search...'}"
|
||||
style="margin-left: 20px;">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !authorized-users -->
|
||||
</div>
|
|
@ -1,55 +0,0 @@
|
|||
angular.module('common.accesscontrol.form', [])
|
||||
.controller('AccessControlFormController', ['$q', '$scope', '$state', 'UserService', 'ResourceControlService', 'Notifications', 'Authentication', 'ModalService', 'ControllerDataPipeline',
|
||||
function ($q, $scope, $state, UserService, ResourceControlService, Notifications, Authentication, ModalService, ControllerDataPipeline) {
|
||||
|
||||
$scope.availableTeams = [];
|
||||
$scope.availableUsers = [];
|
||||
|
||||
$scope.formValues = {
|
||||
enableAccessControl: true,
|
||||
Ownership_Teams: [],
|
||||
Ownership_Users: [],
|
||||
Ownership: 'private'
|
||||
};
|
||||
|
||||
$scope.synchronizeFormData = function() {
|
||||
ControllerDataPipeline.setAccessControlFormData($scope.formValues.enableAccessControl,
|
||||
$scope.formValues.Ownership, $scope.formValues.Ownership_Users, $scope.formValues.Ownership_Teams);
|
||||
};
|
||||
|
||||
function initAccessControlForm() {
|
||||
$('#loadingViewSpinner').show();
|
||||
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var isAdmin = userDetails.role === 1 ? true: false;
|
||||
$scope.isAdmin = isAdmin;
|
||||
|
||||
if (isAdmin) {
|
||||
$scope.formValues.Ownership = 'administrators';
|
||||
}
|
||||
|
||||
$q.all({
|
||||
availableTeams: UserService.userTeams(userDetails.ID),
|
||||
availableUsers: isAdmin ? UserService.users(false) : []
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.availableUsers = data.availableUsers;
|
||||
|
||||
var availableTeams = data.availableTeams;
|
||||
$scope.availableTeams = availableTeams;
|
||||
if (!isAdmin && availableTeams.length === 1) {
|
||||
$scope.formValues.Ownership_Teams = availableTeams;
|
||||
}
|
||||
|
||||
$scope.synchronizeFormData();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve access control information');
|
||||
})
|
||||
.finally(function final() {
|
||||
$('#loadingViewSpinner').hide();
|
||||
});
|
||||
}
|
||||
|
||||
initAccessControlForm();
|
||||
}]);
|
|
@ -1,158 +0,0 @@
|
|||
angular.module('common.accesscontrol.panel', [])
|
||||
.controller('AccessControlPanelController', ['$q', '$scope', '$state', 'UserService', 'ResourceControlService', 'Notifications', 'Authentication', 'ModalService', 'ControllerDataPipeline', 'FormValidator',
|
||||
function ($q, $scope, $state, UserService, ResourceControlService, Notifications, Authentication, ModalService, ControllerDataPipeline, FormValidator) {
|
||||
|
||||
$scope.state = {
|
||||
displayAccessControlPanel: false,
|
||||
canEditOwnership: false,
|
||||
editOwnership: false,
|
||||
formValidationError: ''
|
||||
};
|
||||
|
||||
$scope.formValues = {
|
||||
Ownership: 'public',
|
||||
Ownership_Users: [],
|
||||
Ownership_Teams: []
|
||||
};
|
||||
|
||||
$scope.authorizedUsers = [];
|
||||
$scope.availableUsers = [];
|
||||
$scope.authorizedTeams = [];
|
||||
$scope.availableTeams = [];
|
||||
|
||||
$scope.confirmUpdateOwnership = function (force) {
|
||||
if (!validateForm()) {
|
||||
return;
|
||||
}
|
||||
ModalService.confirmAccessControlUpdate(function (confirmed) {
|
||||
if(!confirmed) { return; }
|
||||
updateOwnership();
|
||||
});
|
||||
};
|
||||
|
||||
function processOwnershipFormValues() {
|
||||
var userIds = [];
|
||||
angular.forEach($scope.formValues.Ownership_Users, function(user) {
|
||||
userIds.push(user.Id);
|
||||
});
|
||||
var teamIds = [];
|
||||
angular.forEach($scope.formValues.Ownership_Teams, function(team) {
|
||||
teamIds.push(team.Id);
|
||||
});
|
||||
var administratorsOnly = $scope.formValues.Ownership === 'administrators' ? true : false;
|
||||
|
||||
return {
|
||||
ownership: $scope.formValues.Ownership,
|
||||
authorizedUserIds: administratorsOnly ? [] : userIds,
|
||||
authorizedTeamIds: administratorsOnly ? [] : teamIds,
|
||||
administratorsOnly: administratorsOnly
|
||||
};
|
||||
}
|
||||
|
||||
function validateForm() {
|
||||
$scope.state.formValidationError = '';
|
||||
var error = '';
|
||||
|
||||
var accessControlData = {
|
||||
ownership: $scope.formValues.Ownership,
|
||||
authorizedUsers: $scope.formValues.Ownership_Users,
|
||||
authorizedTeams: $scope.formValues.Ownership_Teams
|
||||
};
|
||||
var isAdmin = $scope.isAdmin;
|
||||
error = FormValidator.validateAccessControl(accessControlData, isAdmin);
|
||||
if (error) {
|
||||
$scope.state.formValidationError = error;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function updateOwnership() {
|
||||
$('#loadingViewSpinner').show();
|
||||
|
||||
var accessControlData = ControllerDataPipeline.getAccessControlData();
|
||||
var resourceId = accessControlData.resourceId;
|
||||
var ownershipParameters = processOwnershipFormValues();
|
||||
|
||||
ResourceControlService.applyResourceControlChange(accessControlData.resourceType, resourceId,
|
||||
$scope.resourceControl, ownershipParameters)
|
||||
.then(function success(data) {
|
||||
Notifications.success('Access control successfully updated');
|
||||
$state.reload();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to update access control');
|
||||
})
|
||||
.finally(function final() {
|
||||
$('#loadingViewSpinner').hide();
|
||||
});
|
||||
}
|
||||
|
||||
function initAccessControlPanel() {
|
||||
$('#loadingViewSpinner').show();
|
||||
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var isAdmin = userDetails.role === 1 ? true: false;
|
||||
var userId = userDetails.ID;
|
||||
$scope.isAdmin = isAdmin;
|
||||
|
||||
var accessControlData = ControllerDataPipeline.getAccessControlData();
|
||||
var resourceControl = accessControlData.resourceControl;
|
||||
$scope.resourceType = accessControlData.resourceType;
|
||||
$scope.resourceControl = resourceControl;
|
||||
|
||||
if (isAdmin) {
|
||||
if (resourceControl) {
|
||||
$scope.formValues.Ownership = resourceControl.Ownership === 'private' ? 'restricted' : resourceControl.Ownership;
|
||||
} else {
|
||||
$scope.formValues.Ownership = 'public';
|
||||
}
|
||||
} else {
|
||||
$scope.formValues.Ownership = 'public';
|
||||
}
|
||||
|
||||
ResourceControlService.retrieveOwnershipDetails(resourceControl)
|
||||
.then(function success(data) {
|
||||
$scope.authorizedUsers = data.authorizedUsers;
|
||||
$scope.authorizedTeams = data.authorizedTeams;
|
||||
return ResourceControlService.retrieveUserPermissionsOnResource(userId, isAdmin, resourceControl);
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.state.canEditOwnership = data.isPartOfRestrictedUsers || data.isLeaderOfAnyRestrictedTeams;
|
||||
$scope.state.canChangeOwnershipToTeam = data.isPartOfRestrictedUsers;
|
||||
|
||||
return $q.all({
|
||||
availableUsers: isAdmin ? UserService.users(false) : [],
|
||||
availableTeams: isAdmin || data.isPartOfRestrictedUsers ? UserService.userTeams(userId) : []
|
||||
});
|
||||
})
|
||||
.then(function success(data) {
|
||||
$scope.availableUsers = data.availableUsers;
|
||||
angular.forEach($scope.availableUsers, function(user) {
|
||||
var found = _.find($scope.authorizedUsers, { Id: user.Id });
|
||||
if (found) {
|
||||
user.selected = true;
|
||||
}
|
||||
});
|
||||
$scope.availableTeams = data.availableTeams;
|
||||
angular.forEach(data.availableTeams, function(team) {
|
||||
var found = _.find($scope.authorizedTeams, { Id: team.Id });
|
||||
if (found) {
|
||||
team.selected = true;
|
||||
}
|
||||
});
|
||||
if (data.availableTeams.length === 1) {
|
||||
$scope.formValues.Ownership_Teams.push(data.availableTeams[0]);
|
||||
}
|
||||
$scope.state.displayAccessControlPanel = true;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve access control information');
|
||||
})
|
||||
.finally(function final() {
|
||||
$('#loadingViewSpinner').hide();
|
||||
});
|
||||
}
|
||||
|
||||
initAccessControlPanel();
|
||||
}]);
|
|
@ -87,7 +87,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-include="'app/components/common/accessControlPanel/accessControlPanel.html'" ng-if="container && applicationState.application.authentication"></div>
|
||||
<!-- access-control-panel -->
|
||||
<por-access-control-panel
|
||||
ng-if="container && applicationState.application.authentication"
|
||||
resource-control="container.ResourceControl"
|
||||
resource-type="'container'">
|
||||
</por-access-control-panel>
|
||||
<!-- !access-control-panel -->
|
||||
|
||||
<div ng-if="container.State.Health" class="row">
|
||||
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('container', [])
|
||||
.controller('ContainerController', ['$scope', '$state','$stateParams', '$filter', 'Container', 'ContainerCommit', 'ContainerService', 'ImageHelper', 'Network', 'Notifications', 'Pagination', 'ModalService', 'ControllerDataPipeline',
|
||||
function ($scope, $state, $stateParams, $filter, Container, ContainerCommit, ContainerService, ImageHelper, Network, Notifications, Pagination, ModalService, ControllerDataPipeline) {
|
||||
.controller('ContainerController', ['$scope', '$state','$stateParams', '$filter', 'Container', 'ContainerCommit', 'ContainerService', 'ImageHelper', 'Network', 'Notifications', 'Pagination', 'ModalService',
|
||||
function ($scope, $state, $stateParams, $filter, Container, ContainerCommit, ContainerService, ImageHelper, Network, Notifications, Pagination, ModalService) {
|
||||
$scope.activityTime = 0;
|
||||
$scope.portBindings = [];
|
||||
$scope.config = {
|
||||
|
@ -19,7 +19,6 @@ function ($scope, $state, $stateParams, $filter, Container, ContainerCommit, Con
|
|||
Container.get({id: $stateParams.id}, function (d) {
|
||||
var container = new ContainerDetailsViewModel(d);
|
||||
$scope.container = container;
|
||||
ControllerDataPipeline.setAccessControlData('container', $stateParams.id, container.ResourceControl);
|
||||
$scope.container.edit = false;
|
||||
$scope.container.newContainerName = $filter('trimcontainername')(container.Name);
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// @@OLD_SERVICE_CONTROLLER: this service should be rewritten to use services.
|
||||
// See app/components/templates/templatesController.js as a reference.
|
||||
angular.module('createContainer', [])
|
||||
.controller('CreateContainerController', ['$q', '$scope', '$state', '$stateParams', '$filter', 'Container', 'ContainerHelper', 'Image', 'ImageHelper', 'Volume', 'Network', 'ResourceControlService', 'Authentication', 'Notifications', 'ContainerService', 'ImageService', 'ControllerDataPipeline', 'FormValidator',
|
||||
function ($q, $scope, $state, $stateParams, $filter, Container, ContainerHelper, Image, ImageHelper, Volume, Network, ResourceControlService, Authentication, Notifications, ContainerService, ImageService, ControllerDataPipeline, FormValidator) {
|
||||
.controller('CreateContainerController', ['$q', '$scope', '$state', '$stateParams', '$filter', 'Container', 'ContainerHelper', 'Image', 'ImageHelper', 'Volume', 'Network', 'ResourceControlService', 'Authentication', 'Notifications', 'ContainerService', 'ImageService', 'FormValidator',
|
||||
function ($q, $scope, $state, $stateParams, $filter, Container, ContainerHelper, Image, ImageHelper, Volume, Network, ResourceControlService, Authentication, Notifications, ContainerService, ImageService, FormValidator) {
|
||||
|
||||
$scope.formValues = {
|
||||
alwaysPull: true,
|
||||
|
@ -13,7 +13,8 @@ function ($q, $scope, $state, $stateParams, $filter, Container, ContainerHelper,
|
|||
Labels: [],
|
||||
ExtraHosts: [],
|
||||
IPv4: '',
|
||||
IPv6: ''
|
||||
IPv6: '',
|
||||
AccessControlData: new AccessControlFormData()
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
|
@ -285,7 +286,7 @@ function ($q, $scope, $state, $stateParams, $filter, Container, ContainerHelper,
|
|||
$scope.create = function () {
|
||||
$('#createContainerSpinner').show();
|
||||
|
||||
var accessControlData = ControllerDataPipeline.getAccessControlFormData();
|
||||
var accessControlData = $scope.formValues.AccessControlData;
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var isAdmin = userDetails.role === 1 ? true : false;
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
</div>
|
||||
<!-- !port-mapping -->
|
||||
<!-- access-control -->
|
||||
<div ng-include="'app/components/common/accessControlForm/accessControlForm.html'" ng-if="applicationState.application.authentication"></div>
|
||||
<por-access-control-form form-data="formValues.AccessControlData"></por-access-control-form>
|
||||
<!-- !access-control -->
|
||||
<!-- actions -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// @@OLD_SERVICE_CONTROLLER: this service should be rewritten to use services.
|
||||
// See app/components/templates/templatesController.js as a reference.
|
||||
angular.module('createService', [])
|
||||
.controller('CreateServiceController', ['$q', '$scope', '$state', 'Service', 'ServiceHelper', 'SecretHelper', 'SecretService', 'VolumeService', 'NetworkService', 'ImageHelper', 'LabelHelper', 'Authentication', 'ResourceControlService', 'Notifications', 'ControllerDataPipeline', 'FormValidator', 'RegistryService', 'HttpRequestHelper',
|
||||
function ($q, $scope, $state, Service, ServiceHelper, SecretHelper, SecretService, VolumeService, NetworkService, ImageHelper, LabelHelper, Authentication, ResourceControlService, Notifications, ControllerDataPipeline, FormValidator, RegistryService, HttpRequestHelper) {
|
||||
.controller('CreateServiceController', ['$q', '$scope', '$state', 'Service', 'ServiceHelper', 'SecretHelper', 'SecretService', 'VolumeService', 'NetworkService', 'ImageHelper', 'LabelHelper', 'Authentication', 'ResourceControlService', 'Notifications', 'FormValidator', 'RegistryService', 'HttpRequestHelper',
|
||||
function ($q, $scope, $state, Service, ServiceHelper, SecretHelper, SecretService, VolumeService, NetworkService, ImageHelper, LabelHelper, Authentication, ResourceControlService, Notifications, FormValidator, RegistryService, HttpRequestHelper) {
|
||||
|
||||
$scope.formValues = {
|
||||
Name: '',
|
||||
|
@ -26,7 +26,8 @@ function ($q, $scope, $state, Service, ServiceHelper, SecretHelper, SecretServic
|
|||
PlacementPreferences: [],
|
||||
UpdateDelay: 0,
|
||||
FailureAction: 'pause',
|
||||
Secrets: []
|
||||
Secrets: [],
|
||||
AccessControlData: new AccessControlFormData()
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
|
@ -286,7 +287,7 @@ function ($q, $scope, $state, Service, ServiceHelper, SecretHelper, SecretServic
|
|||
$scope.create = function createService() {
|
||||
$('#createServiceSpinner').show();
|
||||
|
||||
var accessControlData = ControllerDataPipeline.getAccessControlFormData();
|
||||
var accessControlData = $scope.formValues.AccessControlData;
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var isAdmin = userDetails.role === 1 ? true : false;
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
</div>
|
||||
<!-- !port-mapping -->
|
||||
<!-- access-control -->
|
||||
<div ng-include="'app/components/common/accessControlForm/accessControlForm.html'" ng-if="applicationState.application.authentication"></div>
|
||||
<por-access-control-form form-data="formValues.AccessControlData"></por-access-control-form>
|
||||
<!-- !access-control -->
|
||||
<!-- actions -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
angular.module('createVolume', [])
|
||||
.controller('CreateVolumeController', ['$scope', '$state', 'VolumeService', 'SystemService', 'ResourceControlService', 'Authentication', 'Notifications', 'ControllerDataPipeline', 'FormValidator',
|
||||
function ($scope, $state, VolumeService, SystemService, ResourceControlService, Authentication, Notifications, ControllerDataPipeline, FormValidator) {
|
||||
.controller('CreateVolumeController', ['$scope', '$state', 'VolumeService', 'SystemService', 'ResourceControlService', 'Authentication', 'Notifications', 'FormValidator',
|
||||
function ($scope, $state, VolumeService, SystemService, ResourceControlService, Authentication, Notifications, FormValidator) {
|
||||
|
||||
$scope.formValues = {
|
||||
Driver: 'local',
|
||||
DriverOptions: []
|
||||
DriverOptions: [],
|
||||
AccessControlData: new AccessControlFormData()
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
|
@ -40,8 +41,8 @@ function ($scope, $state, VolumeService, SystemService, ResourceControlService,
|
|||
var driver = $scope.formValues.Driver;
|
||||
var driverOptions = $scope.formValues.DriverOptions;
|
||||
var volumeConfiguration = VolumeService.createVolumeConfiguration(name, driver, driverOptions);
|
||||
var accessControlData = $scope.formValues.AccessControlData;
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var accessControlData = ControllerDataPipeline.getAccessControlFormData();
|
||||
var isAdmin = userDetails.role === 1 ? true : false;
|
||||
|
||||
if (!validateForm(accessControlData, isAdmin)) {
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
</div>
|
||||
<!-- !driver-options -->
|
||||
<!-- access-control -->
|
||||
<div ng-include="'app/components/common/accessControlForm/accessControlForm.html'" ng-if="applicationState.application.authentication"></div>
|
||||
<por-access-control-form form-data="formValues.AccessControlData"></por-access-control-form>
|
||||
<!-- !access-control -->
|
||||
<!-- actions -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
|
|
|
@ -125,7 +125,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-include="'app/components/common/accessControlPanel/accessControlPanel.html'" ng-if="service && applicationState.application.authentication"></div>
|
||||
<!-- access-control-panel -->
|
||||
<por-access-control-panel
|
||||
ng-if="service && applicationState.application.authentication"
|
||||
resource-control="service.ResourceControl"
|
||||
resource-type="'service'">
|
||||
</por-access-control-panel>
|
||||
<!-- !access-control-panel -->
|
||||
|
||||
<div class="row">
|
||||
<hr>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('service', [])
|
||||
.controller('ServiceController', ['$q', '$scope', '$stateParams', '$state', '$location', '$timeout', '$anchorScroll', 'ServiceService', 'Secret', 'SecretHelper', 'Service', 'ServiceHelper', 'LabelHelper', 'TaskService', 'NodeService', 'Notifications', 'Pagination', 'ModalService', 'ControllerDataPipeline',
|
||||
function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll, ServiceService, Secret, SecretHelper, Service, ServiceHelper, LabelHelper, TaskService, NodeService, Notifications, Pagination, ModalService, ControllerDataPipeline) {
|
||||
.controller('ServiceController', ['$q', '$scope', '$stateParams', '$state', '$location', '$timeout', '$anchorScroll', 'ServiceService', 'Secret', 'SecretHelper', 'Service', 'ServiceHelper', 'LabelHelper', 'TaskService', 'NodeService', 'Notifications', 'Pagination', 'ModalService',
|
||||
function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll, ServiceService, Secret, SecretHelper, Service, ServiceHelper, LabelHelper, TaskService, NodeService, Notifications, Pagination, ModalService) {
|
||||
|
||||
$scope.state = {};
|
||||
$scope.state.pagination_count = Pagination.getPaginationCount('service_tasks');
|
||||
|
@ -299,7 +299,6 @@ function ($q, $scope, $stateParams, $state, $location, $timeout, $anchorScroll,
|
|||
|
||||
translateServiceArrays(service);
|
||||
$scope.service = service;
|
||||
ControllerDataPipeline.setAccessControlData('service', $stateParams.id, service.ResourceControl);
|
||||
originalService = angular.copy(service);
|
||||
|
||||
return $q.all({
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
</div>
|
||||
<!-- !env -->
|
||||
<!-- access-control -->
|
||||
<div ng-include="'app/components/common/accessControlForm/accessControlForm.html'" ng-if="applicationState.application.authentication"></div>
|
||||
<por-access-control-form form-data="formValues.AccessControlData"></por-access-control-form>
|
||||
<!-- !access-control -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
|
@ -202,13 +202,14 @@
|
|||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.network" ng-click="createTemplate()">Create</button>
|
||||
<i id="createContainerSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
|
||||
<span class="small text-muted" style="margin-left: 10px" ng-if="globalNetworkCount === 0 && applicationState.endpoint.mode.provider === 'DOCKER_SWARM'">
|
||||
<span class="small text-muted" style="margin-left: 10px" ng-if="globalNetworkCount === 0 && applicationState.endpoint.mode.provider === 'DOCKER_SWARM' && !state.formValidationError">
|
||||
When using Swarm, we recommend deploying containers in a shared network. Looks like you don't have any shared network, head over the <a ui-sref="networks">networks view</a> to create one.
|
||||
</span>
|
||||
<span ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE'" style="margin-left: 10px">
|
||||
<span ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE' && !state.formValidationError" style="margin-left: 10px">
|
||||
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
|
||||
<span class="small text-muted" style="margin-left: 5px;">App templates cannot be deployed as Swarm Mode services for the moment. You can still use them to quickly deploy containers on the Docker host.</span>
|
||||
</span>
|
||||
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !actions -->
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('templates', [])
|
||||
.controller('TemplatesController', ['$scope', '$q', '$state', '$stateParams', '$anchorScroll', '$filter', 'ContainerService', 'ContainerHelper', 'ImageService', 'NetworkService', 'TemplateService', 'TemplateHelper', 'VolumeService', 'Notifications', 'Pagination', 'ResourceControlService', 'Authentication', 'ControllerDataPipeline', 'FormValidator',
|
||||
function ($scope, $q, $state, $stateParams, $anchorScroll, $filter, ContainerService, ContainerHelper, ImageService, NetworkService, TemplateService, TemplateHelper, VolumeService, Notifications, Pagination, ResourceControlService, Authentication, ControllerDataPipeline, FormValidator) {
|
||||
.controller('TemplatesController', ['$scope', '$q', '$state', '$stateParams', '$anchorScroll', '$filter', 'ContainerService', 'ContainerHelper', 'ImageService', 'NetworkService', 'TemplateService', 'TemplateHelper', 'VolumeService', 'Notifications', 'Pagination', 'ResourceControlService', 'Authentication', 'FormValidator',
|
||||
function ($scope, $q, $state, $stateParams, $anchorScroll, $filter, ContainerService, ContainerHelper, ImageService, NetworkService, TemplateService, TemplateHelper, VolumeService, Notifications, Pagination, ResourceControlService, Authentication, FormValidator) {
|
||||
$scope.state = {
|
||||
selectedTemplate: null,
|
||||
showAdvancedOptions: false,
|
||||
|
@ -14,7 +14,8 @@ function ($scope, $q, $state, $stateParams, $anchorScroll, $filter, ContainerSer
|
|||
|
||||
$scope.formValues = {
|
||||
network: '',
|
||||
name: ''
|
||||
name: '',
|
||||
AccessControlData: new AccessControlFormData()
|
||||
};
|
||||
|
||||
$scope.addVolume = function () {
|
||||
|
@ -49,7 +50,7 @@ function ($scope, $q, $state, $stateParams, $anchorScroll, $filter, ContainerSer
|
|||
$('#createContainerSpinner').show();
|
||||
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var accessControlData = ControllerDataPipeline.getAccessControlFormData();
|
||||
var accessControlData = $scope.formValues.AccessControlData;
|
||||
var isAdmin = userDetails.role === 1 ? true : false;
|
||||
|
||||
if (!validateForm(accessControlData, isAdmin)) {
|
||||
|
|
|
@ -47,7 +47,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-include="'app/components/common/accessControlPanel/accessControlPanel.html'" ng-if="volume && applicationState.application.authentication"></div>
|
||||
<!-- access-control-panel -->
|
||||
<por-access-control-panel
|
||||
ng-if="volume && applicationState.application.authentication"
|
||||
resource-control="volume.ResourceControl"
|
||||
resource-type="'volume'">
|
||||
</por-access-control-panel>
|
||||
<!-- !access-control-panel -->
|
||||
|
||||
<div class="row" ng-if="!(volume.Options | emptyobject)">
|
||||
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('volume', [])
|
||||
.controller('VolumeController', ['$scope', '$state', '$stateParams', 'VolumeService', 'Notifications', 'ControllerDataPipeline',
|
||||
function ($scope, $state, $stateParams, VolumeService, Notifications, ControllerDataPipeline) {
|
||||
.controller('VolumeController', ['$scope', '$state', '$stateParams', 'VolumeService', 'Notifications',
|
||||
function ($scope, $state, $stateParams, VolumeService, Notifications) {
|
||||
|
||||
$scope.removeVolume = function removeVolume() {
|
||||
$('#loadingViewSpinner').show();
|
||||
|
@ -22,7 +22,6 @@ function ($scope, $state, $stateParams, VolumeService, Notifications, Controller
|
|||
VolumeService.volume($stateParams.id)
|
||||
.then(function success(data) {
|
||||
var volume = data;
|
||||
ControllerDataPipeline.setAccessControlData('volume', volume.Id, volume.ResourceControl);
|
||||
$scope.volume = volume;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
angular.module('portainer').component('porAccessControlForm', {
|
||||
templateUrl: 'app/directives/accessControlForm/porAccessControlForm.html',
|
||||
controller: 'porAccessControlFormController',
|
||||
bindings: {
|
||||
// This object will be populated with the form data.
|
||||
// Model reference in porAccessControlFromModel.js
|
||||
formData: '=',
|
||||
// Optional. An existing resource control object that will be used to set
|
||||
// the default values of the component.
|
||||
resourceControl: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,124 @@
|
|||
<div>
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Access control
|
||||
</div>
|
||||
<!-- access-control-switch -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="ownership" class="control-label text-left">
|
||||
Enable access control
|
||||
<portainer-tooltip position="bottom" message="When enabled, you can restrict the access and management of this resource."></portainer-tooltip>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input name="ownership" type="checkbox" ng-model="$ctrl.formData.AccessControlEnabled"><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !access-control-switch -->
|
||||
<!-- restricted-access -->
|
||||
<div class="form-group" ng-if="$ctrl.formData.AccessControlEnabled" style="margin-bottom: 0">
|
||||
<div class="boxselector_wrapper">
|
||||
<div ng-if="$ctrl.isAdmin">
|
||||
<input type="radio" id="access_administrators" ng-model="$ctrl.formData.Ownership" value="administrators">
|
||||
<label for="access_administrators">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'administrators' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Administrators
|
||||
</div>
|
||||
<p>I want to restrict the management of this resource to administrators only</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="$ctrl.isAdmin">
|
||||
<input type="radio" id="access_restricted" ng-model="$ctrl.formData.Ownership" value="restricted">
|
||||
<label for="access_restricted">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'restricted' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Restricted
|
||||
</div>
|
||||
<p>
|
||||
I want to restrict the management of this resource to a set of users and/or teams
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="!$ctrl.isAdmin">
|
||||
<input type="radio" id="access_private" ng-model="$ctrl.formData.Ownership" value="private">
|
||||
<label for="access_private">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'private' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Private
|
||||
</div>
|
||||
<p>
|
||||
I want to this resource to be manageable by myself only
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="!$ctrl.isAdmin && $ctrl.availableTeams.length > 0">
|
||||
<input type="radio" id="access_restricted" ng-model="$ctrl.formData.Ownership" value="restricted">
|
||||
<label for="access_restricted">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'restricted' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Restricted
|
||||
</div>
|
||||
<p ng-if="$ctrl.availableTeams.length === 1">
|
||||
I want any member of my team (<b>{{ $ctrl.availableTeams[0].Name }}</b>) to be able to manage this resource
|
||||
</p>
|
||||
<p ng-if="$ctrl.availableTeams.length > 1">
|
||||
I want to restrict the management of this resource to one or more of my teams
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- restricted-access -->
|
||||
<!-- authorized-teams -->
|
||||
<div class="form-group" ng-if="$ctrl.formData.AccessControlEnabled && $ctrl.formData.Ownership === 'restricted' && ($ctrl.isAdmin || (!$ctrl.isAdmin && $ctrl.availableTeams.length > 1))" >
|
||||
<div class="col-sm-12">
|
||||
<label for="group-access" class="control-label text-left">
|
||||
Authorized teams
|
||||
<portainer-tooltip ng-if="$ctrl.isAdmin && $ctrl.availableTeams.length > 0" position="bottom" message="You can select which teams(s) will be able to manage this resource."></portainer-tooltip>
|
||||
<portainer-tooltip ng-if="!$ctrl.isAdmin && $ctrl.availableTeams.length > 1" position="bottom" message="As you are a member of multiple teams, you can select which teams(s) will be able to manage this resource."></portainer-tooltip>
|
||||
</label>
|
||||
<span ng-if="$ctrl.isAdmin && $ctrl.availableTeams.length === 0" class="small text-muted" style="margin-left: 20px;">
|
||||
You have not yet created any team. Head over the <a ui-sref="teams">teams view</a> to manage user teams.
|
||||
</span>
|
||||
<span isteven-multi-select
|
||||
ng-if="($ctrl.isAdmin && $ctrl.availableTeams.length > 0) || (!$ctrl.isAdmin && $ctrl.availableTeams.length > 1)"
|
||||
input-model="$ctrl.availableTeams"
|
||||
output-model="$ctrl.formData.AuthorizedTeams"
|
||||
button-label="Name"
|
||||
item-label="Name"
|
||||
tick-property="selected"
|
||||
helper-elements="filter"
|
||||
search-property="Name"
|
||||
translation="{nothingSelected: 'Select one or more teams', search: 'Search...'}"
|
||||
style="margin-left: 20px;">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !authorized-teams -->
|
||||
<!-- authorized-users -->
|
||||
<div class="form-group" ng-if="$ctrl.formData.AccessControlEnabled && $ctrl.formData.Ownership === 'restricted' && $ctrl.isAdmin">
|
||||
<div class="col-sm-12">
|
||||
<label for="group-access" class="control-label text-left">
|
||||
Authorized users
|
||||
<portainer-tooltip ng-if="$ctrl.isAdmin && $ctrl.availableUsers.length > 0" position="bottom" message="You can select which user(s) will be able to manage this resource."></portainer-tooltip>
|
||||
</label>
|
||||
<span ng-if="$ctrl.availableUsers.length === 0" class="small text-muted" style="margin-left: 20px;">
|
||||
You have not yet created any user. Head over the <a ui-sref="users">users view</a> to manage users.
|
||||
</span>
|
||||
<span isteven-multi-select
|
||||
ng-if="$ctrl.availableUsers.length > 0"
|
||||
input-model="$ctrl.availableUsers"
|
||||
output-model="$ctrl.formData.AuthorizedUsers"
|
||||
button-label="Username"
|
||||
item-label="Username"
|
||||
tick-property="selected"
|
||||
helper-elements="filter"
|
||||
search-property="Username"
|
||||
translation="{nothingSelected: 'Select one or more users', search: 'Search...'}"
|
||||
style="margin-left: 20px;">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !authorized-users -->
|
||||
</div>
|
|
@ -0,0 +1,76 @@
|
|||
angular.module('portainer')
|
||||
.controller('porAccessControlFormController', ['$q', 'UserService', 'Notifications', 'Authentication', 'ResourceControlService',
|
||||
function ($q, UserService, Notifications, Authentication, ResourceControlService) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.availableTeams = [];
|
||||
ctrl.availableUsers = [];
|
||||
|
||||
function setOwnership(resourceControl, isAdmin) {
|
||||
if (isAdmin && resourceControl.Ownership === 'private') {
|
||||
ctrl.formData.Ownership = 'restricted';
|
||||
} else {
|
||||
ctrl.formData.Ownership = resourceControl.Ownership;
|
||||
}
|
||||
}
|
||||
|
||||
function setAuthorizedUsersAndTeams(authorizedUsers, authorizedTeams) {
|
||||
angular.forEach(ctrl.availableUsers, function(user) {
|
||||
var found = _.find(authorizedUsers, { Id: user.Id });
|
||||
if (found) {
|
||||
user.selected = true;
|
||||
}
|
||||
});
|
||||
|
||||
angular.forEach(ctrl.availableTeams, function(team) {
|
||||
var found = _.find(authorizedTeams, { Id: team.Id });
|
||||
if (found) {
|
||||
team.selected = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initComponent() {
|
||||
$('#loadingViewSpinner').show();
|
||||
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var isAdmin = userDetails.role === 1 ? true: false;
|
||||
ctrl.isAdmin = isAdmin;
|
||||
|
||||
if (isAdmin) {
|
||||
ctrl.formData.Ownership = 'administrators';
|
||||
}
|
||||
|
||||
$q.all({
|
||||
availableTeams: UserService.userTeams(userDetails.ID),
|
||||
availableUsers: isAdmin ? UserService.users(false) : []
|
||||
})
|
||||
.then(function success(data) {
|
||||
ctrl.availableUsers = data.availableUsers;
|
||||
|
||||
var availableTeams = data.availableTeams;
|
||||
ctrl.availableTeams = availableTeams;
|
||||
if (!isAdmin && availableTeams.length === 1) {
|
||||
ctrl.formData.AuthorizedTeams = availableTeams;
|
||||
}
|
||||
|
||||
return $q.when(ctrl.resourceControl && ResourceControlService.retrieveOwnershipDetails(ctrl.resourceControl));
|
||||
})
|
||||
.then(function success(data) {
|
||||
if (data) {
|
||||
var authorizedUsers = data.authorizedUsers;
|
||||
var authorizedTeams = data.authorizedTeams;
|
||||
setOwnership(ctrl.resourceControl, isAdmin);
|
||||
setAuthorizedUsersAndTeams(authorizedUsers, authorizedTeams);
|
||||
}
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve access control information');
|
||||
})
|
||||
.finally(function final() {
|
||||
$('#loadingViewSpinner').hide();
|
||||
});
|
||||
}
|
||||
|
||||
initComponent();
|
||||
}]);
|
|
@ -0,0 +1,6 @@
|
|||
function AccessControlFormData() {
|
||||
this.AccessControlEnabled = true;
|
||||
this.Ownership = 'private';
|
||||
this.AuthorizedUsers = [];
|
||||
this.AuthorizedTeams = [];
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
angular.module('portainer').component('porAccessControlPanel', {
|
||||
templateUrl: 'app/directives/accessControlPanel/porAccessControlPanel.html',
|
||||
controller: 'porAccessControlPanelController',
|
||||
bindings: {
|
||||
// The component will display information about this resource control object.
|
||||
resourceControl: '=',
|
||||
// This component is usually displayed inside a resource-details view.
|
||||
// This variable specifies the type of the associated resource.
|
||||
// Accepted values: 'container', 'service' or 'volume'.
|
||||
resourceType: '<'
|
||||
}
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
<div class="row" ng-controller="AccessControlPanelController">
|
||||
<div class="col-sm-12" ng-if="state.displayAccessControlPanel">
|
||||
<div class="row">
|
||||
<div class="col-sm-12" ng-if="$ctrl.state.displayAccessControlPanel">
|
||||
<rd-widget>
|
||||
<rd-widget-header icon="fa-eye" title="Access control"></rd-widget-header>
|
||||
<rd-widget-body classes="no-padding">
|
||||
|
@ -9,63 +9,63 @@
|
|||
<tr>
|
||||
<td>Ownership</td>
|
||||
<td>
|
||||
<i ng-class="resourceControl.Ownership | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
<span ng-if="!resourceControl">
|
||||
<i ng-class="$ctrl.resourceControl.Ownership | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
<span ng-if="!$ctrl.resourceControl">
|
||||
public
|
||||
<portainer-tooltip message="This resource can be managed by any user with access to this endpoint." position="bottom" style="margin-left: -3px;"></portainer-tooltip>
|
||||
</span>
|
||||
<span ng-if="resourceControl">
|
||||
{{ resourceControl.Ownership }}
|
||||
<portainer-tooltip ng-if="resourceControl.Ownership === 'administrators'" message="This resource can only be managed by administrators." position="bottom" style="margin-left: -3px;"></portainer-tooltip>
|
||||
<portainer-tooltip ng-if="resourceControl.Ownership === 'private'" message="Management of this resource is restricted to a single user." position="bottom" style="margin-left: -3px;"></portainer-tooltip>
|
||||
<portainer-tooltip ng-if="resourceControl.Ownership === 'restricted'" message="This resource can be managed by a restricted set of users and/or teams." position="bottom" style="margin-left: -3px;"></portainer-tooltip>
|
||||
<span ng-if="$ctrl.resourceControl">
|
||||
{{ $ctrl.resourceControl.Ownership }}
|
||||
<portainer-tooltip ng-if="$ctrl.resourceControl.Ownership === 'administrators'" message="This resource can only be managed by administrators." position="bottom" style="margin-left: -3px;"></portainer-tooltip>
|
||||
<portainer-tooltip ng-if="$ctrl.resourceControl.Ownership === 'private'" message="Management of this resource is restricted to a single user." position="bottom" style="margin-left: -3px;"></portainer-tooltip>
|
||||
<portainer-tooltip ng-if="$ctrl.resourceControl.Ownership === 'restricted'" message="This resource can be managed by a restricted set of users and/or teams." position="bottom" style="margin-left: -3px;"></portainer-tooltip>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- !ownership -->
|
||||
<tr ng-if="resourceControl.Type === 2 && resourceType === 'container'">
|
||||
<tr ng-if="$ctrl.resourceControl.Type === 2 && $ctrl.resourceType === 'container'">
|
||||
<td colspan="2">
|
||||
<i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Access control on this resource is inherited from the following service: <a ui-sref="service({ id: resourceControl.ResourceId })">{{ resourceControl.ResourceId | truncate }}</a>
|
||||
Access control on this resource is inherited from the following service: <a ui-sref="service({ id: $ctrl.resourceControl.ResourceId })">{{ $ctrl.resourceControl.ResourceId | truncate }}</a>
|
||||
<portainer-tooltip message="Access control applied on a service is also applied on each container of that service." position="bottom" style="margin-left: 2px;"></portainer-tooltip>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="resourceControl.Type === 1 && resourceType === 'volume'">
|
||||
<tr ng-if="$ctrl.resourceControl.Type === 1 && $ctrl.resourceType === 'volume'">
|
||||
<td colspan="2">
|
||||
<i class="fa fa-info-circle" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Access control on this resource is inherited from the following container: <a ui-sref="container({ id: resourceControl.ResourceId })">{{ resourceControl.ResourceId | truncate }}</a>
|
||||
Access control on this resource is inherited from the following container: <a ui-sref="container({ id: $ctrl.resourceControl.ResourceId })">{{ $ctrl.resourceControl.ResourceId | truncate }}</a>
|
||||
<portainer-tooltip message="Access control applied on a container created using a template is also applied on each volume associated to the container." position="bottom" style="margin-left: 2px;"></portainer-tooltip>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- authorized-users -->
|
||||
<tr ng-if="resourceControl.UserAccesses.length > 0">
|
||||
<tr ng-if="$ctrl.resourceControl.UserAccesses.length > 0">
|
||||
<td>Authorized users</td>
|
||||
<td>
|
||||
<span ng-repeat="user in authorizedUsers">{{user.Username}}{{$last ? '' : ', '}} </span>
|
||||
<span ng-repeat="user in $ctrl.authorizedUsers">{{user.Username}}{{$last ? '' : ', '}} </span>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- !authorized-users -->
|
||||
<!-- authorized-teams -->
|
||||
<tr ng-if="resourceControl.TeamAccesses.length > 0">
|
||||
<tr ng-if="$ctrl.resourceControl.TeamAccesses.length > 0">
|
||||
<td>Authorized teams</td>
|
||||
<td>
|
||||
<span ng-repeat="team in authorizedTeams">{{team.Name}}{{$last ? '' : ', '}} </span>
|
||||
<span ng-repeat="team in $ctrl.authorizedTeams">{{team.Name}}{{$last ? '' : ', '}} </span>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- !authorized-teams -->
|
||||
<!-- edit-ownership -->
|
||||
<tr ng-if="!(resourceControl.Type === 1 && resourceType === 'volume') && !(resourceControl.Type === 2 && resourceType === 'container') && !state.editOwnership && (isAdmin || state.canEditOwnership)">
|
||||
<tr ng-if="!($ctrl.resourceControl.Type === 1 && $ctrl.resourceType === 'volume') && !($ctrl.resourceControl.Type === 2 && $ctrl.resourceType === 'container') && !$ctrl.state.editOwnership && ($ctrl.isAdmin || $ctrl.state.canEditOwnership)">
|
||||
<td colspan="2">
|
||||
<a class="btn-outline-secondary" ng-click="state.editOwnership = true"><i class="fa fa-edit space-right" aria-hidden="true"></i>Change ownership</a>
|
||||
<a class="btn-outline-secondary" ng-click="$ctrl.state.editOwnership = true"><i class="fa fa-edit space-right" aria-hidden="true"></i>Change ownership</a>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- !edit-ownership -->
|
||||
<!-- edit-ownership-choices -->
|
||||
<tr ng-if="state.editOwnership">
|
||||
<tr ng-if="$ctrl.state.editOwnership">
|
||||
<td colspan="2">
|
||||
<div class="boxselector_wrapper">
|
||||
<div ng-if="isAdmin">
|
||||
<input type="radio" id="access_administrators" ng-model="formValues.Ownership" value="administrators">
|
||||
<div ng-if="$ctrl.isAdmin">
|
||||
<input type="radio" id="access_administrators" ng-model="$ctrl.formValues.Ownership" value="administrators">
|
||||
<label for="access_administrators">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'administrators' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
|
@ -74,8 +74,8 @@
|
|||
<p>I want to restrict the management of this resource to administrators only</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="isAdmin">
|
||||
<input type="radio" id="access_restricted" ng-model="formValues.Ownership" value="restricted">
|
||||
<div ng-if="$ctrl.isAdmin">
|
||||
<input type="radio" id="access_restricted" ng-model="$ctrl.formValues.Ownership" value="restricted">
|
||||
<label for="access_restricted">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'restricted' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
|
@ -86,23 +86,23 @@
|
|||
</p>
|
||||
</label>
|
||||
</div>
|
||||
<div ng-if="!isAdmin && state.canChangeOwnershipToTeam && availableTeams.length > 0">
|
||||
<input type="radio" id="access_restricted" ng-model="formValues.Ownership" value="restricted">
|
||||
<div ng-if="!$ctrl.isAdmin && $ctrl.state.canChangeOwnershipToTeam && $ctrl.availableTeams.length > 0">
|
||||
<input type="radio" id="access_restricted" ng-model="$ctrl.formValues.Ownership" value="restricted">
|
||||
<label for="access_restricted">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'restricted' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Restricted
|
||||
</div>
|
||||
<p ng-if="availableTeams.length === 1">
|
||||
I want any member of my team (<b>{{ availableTeams[0].Name }}</b>) to be able to manage this resource
|
||||
<p ng-if="$ctrl.availableTeams.length === 1">
|
||||
I want any member of my team (<b>{{ $ctrl.availableTeams[0].Name }}</b>) to be able to manage this resource
|
||||
</p>
|
||||
<p ng-if="availableTeams.length > 1">
|
||||
<p ng-if="$ctrl.availableTeams.length > 1">
|
||||
I want to restrict the management of this resource to one or more of my teams
|
||||
</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="access_public" ng-model="formValues.Ownership" value="public">
|
||||
<input type="radio" id="access_public" ng-model="$ctrl.formValues.Ownership" value="public">
|
||||
<label for="access_public">
|
||||
<div class="boxselector_header">
|
||||
<i ng-class="'public' | ownershipicon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
|
@ -116,16 +116,16 @@
|
|||
</tr>
|
||||
<!-- edit-ownership-choices -->
|
||||
<!-- select-teams -->
|
||||
<tr ng-if="state.editOwnership && formValues.Ownership === 'restricted' && (isAdmin || !isAdmin && availableTeams.length > 1)">
|
||||
<tr ng-if="$ctrl.state.editOwnership && $ctrl.formValues.Ownership === 'restricted' && ($ctrl.isAdmin || !$ctrl.isAdmin && $ctrl.availableTeams.length > 1)">
|
||||
<td colspan="2">
|
||||
<span>Teams</span>
|
||||
<span ng-if="isAdmin && availableTeams.length === 0" class="small text-muted" style="margin-left: 10px;">
|
||||
<span ng-if="$ctrl.isAdmin && $ctrl.availableTeams.length === 0" class="small text-muted" style="margin-left: 10px;">
|
||||
You have not yet created any team. Head over the <a ui-sref="teams">teams view</a> to manage user teams.
|
||||
</span>
|
||||
<span isteven-multi-select
|
||||
ng-if="(isAdmin && availableTeams.length > 0) || (!isAdmin && availableTeams.length > 1)"
|
||||
input-model="availableTeams"
|
||||
output-model="formValues.Ownership_Teams"
|
||||
ng-if="($ctrl.isAdmin && $ctrl.availableTeams.length > 0) || (!$ctrl.isAdmin && $ctrl.availableTeams.length > 1)"
|
||||
input-model="$ctrl.availableTeams"
|
||||
output-model="$ctrl.formValues.Ownership_Teams"
|
||||
button-label="Name"
|
||||
item-label="Name"
|
||||
tick-property="selected"
|
||||
|
@ -138,16 +138,16 @@
|
|||
</tr>
|
||||
<!-- !select-teams -->
|
||||
<!-- select-users -->
|
||||
<tr ng-if="isAdmin && state.editOwnership && formValues.Ownership === 'restricted'">
|
||||
<tr ng-if="$ctrl.isAdmin && $ctrl.state.editOwnership && $ctrl.formValues.Ownership === 'restricted'">
|
||||
<td colspan="2">
|
||||
<span>Users</span>
|
||||
<span ng-if="availableUsers.length === 0" class="small text-muted" style="margin-left: 10px;">
|
||||
<span ng-if="$ctrl.availableUsers.length === 0" class="small text-muted" style="margin-left: 10px;">
|
||||
You have not yet created any user. Head over the <a ui-sref="users">users view</a> to manage users.
|
||||
</span>
|
||||
<span isteven-multi-select
|
||||
ng-if="availableUsers.length > 0"
|
||||
input-model="availableUsers"
|
||||
output-model="formValues.Ownership_Users"
|
||||
ng-if="$ctrl.availableUsers.length > 0"
|
||||
input-model="$ctrl.availableUsers"
|
||||
output-model="$ctrl.formValues.Ownership_Users"
|
||||
button-label="Username"
|
||||
item-label="Username"
|
||||
tick-property="selected"
|
||||
|
@ -160,12 +160,12 @@
|
|||
</tr>
|
||||
<!-- !select-users -->
|
||||
<!-- ownership-actions -->
|
||||
<tr ng-if="state.editOwnership">
|
||||
<tr ng-if="$ctrl.state.editOwnership">
|
||||
<td colspan="2">
|
||||
<div>
|
||||
<a type="button" class="btn btn-default btn-sm" ng-click="state.editOwnership = false">Cancel</a>
|
||||
<a type="button" class="btn btn-primary btn-sm" ng-click="confirmUpdateOwnership()">Update ownership</a>
|
||||
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
|
||||
<a type="button" class="btn btn-default btn-sm" ng-click="$ctrl.state.editOwnership = false">Cancel</a>
|
||||
<a type="button" class="btn btn-primary btn-sm" ng-click="$ctrl.confirmUpdateOwnership()">Update ownership</a>
|
||||
<span class="text-danger" ng-if="$ctrl.state.formValidationError" style="margin-left: 5px;">{{ $ctrl.state.formValidationError }}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
|
@ -0,0 +1,156 @@
|
|||
angular.module('portainer')
|
||||
.controller('porAccessControlPanelController', ['$q', '$state', 'UserService', 'ResourceControlService', 'Notifications', 'Authentication', 'ModalService', 'FormValidator',
|
||||
function ($q, $state, UserService, ResourceControlService, Notifications, Authentication, ModalService, FormValidator) {
|
||||
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.state = {
|
||||
displayAccessControlPanel: false,
|
||||
canEditOwnership: false,
|
||||
editOwnership: false,
|
||||
formValidationError: ''
|
||||
};
|
||||
|
||||
ctrl.formValues = {
|
||||
Ownership: 'public',
|
||||
Ownership_Users: [],
|
||||
Ownership_Teams: []
|
||||
};
|
||||
|
||||
ctrl.authorizedUsers = [];
|
||||
ctrl.availableUsers = [];
|
||||
ctrl.authorizedTeams = [];
|
||||
ctrl.availableTeams = [];
|
||||
|
||||
ctrl.confirmUpdateOwnership = function (force) {
|
||||
if (!validateForm()) {
|
||||
return;
|
||||
}
|
||||
ModalService.confirmAccessControlUpdate(function (confirmed) {
|
||||
if(!confirmed) { return; }
|
||||
updateOwnership();
|
||||
});
|
||||
};
|
||||
|
||||
function validateForm() {
|
||||
ctrl.state.formValidationError = '';
|
||||
var error = '';
|
||||
|
||||
var accessControlData = {
|
||||
AccessControlEnabled: ctrl.formValues.Ownership === 'public' ? false : true,
|
||||
Ownership: ctrl.formValues.Ownership,
|
||||
AuthorizedUsers: ctrl.formValues.Ownership_Users,
|
||||
AuthorizedTeams: ctrl.formValues.Ownership_Teams
|
||||
};
|
||||
var isAdmin = ctrl.isAdmin;
|
||||
error = FormValidator.validateAccessControl(accessControlData, isAdmin);
|
||||
if (error) {
|
||||
ctrl.state.formValidationError = error;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function processOwnershipFormValues() {
|
||||
var userIds = [];
|
||||
angular.forEach(ctrl.formValues.Ownership_Users, function(user) {
|
||||
userIds.push(user.Id);
|
||||
});
|
||||
var teamIds = [];
|
||||
angular.forEach(ctrl.formValues.Ownership_Teams, function(team) {
|
||||
teamIds.push(team.Id);
|
||||
});
|
||||
var administratorsOnly = ctrl.formValues.Ownership === 'administrators' ? true : false;
|
||||
|
||||
return {
|
||||
ownership: ctrl.formValues.Ownership,
|
||||
authorizedUserIds: administratorsOnly ? [] : userIds,
|
||||
authorizedTeamIds: administratorsOnly ? [] : teamIds,
|
||||
administratorsOnly: administratorsOnly
|
||||
};
|
||||
}
|
||||
|
||||
function updateOwnership() {
|
||||
$('#loadingViewSpinner').show();
|
||||
|
||||
var resourceId = ctrl.resourceControl.ResourceId;
|
||||
var ownershipParameters = processOwnershipFormValues();
|
||||
|
||||
ResourceControlService.applyResourceControlChange(ctrl.resourceType, resourceId,
|
||||
ctrl.resourceControl, ownershipParameters)
|
||||
.then(function success(data) {
|
||||
Notifications.success('Access control successfully updated');
|
||||
$state.reload();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to update access control');
|
||||
})
|
||||
.finally(function final() {
|
||||
$('#loadingViewSpinner').hide();
|
||||
});
|
||||
}
|
||||
|
||||
function initComponent() {
|
||||
$('#loadingViewSpinner').show();
|
||||
|
||||
var userDetails = Authentication.getUserDetails();
|
||||
var isAdmin = userDetails.role === 1 ? true: false;
|
||||
var userId = userDetails.ID;
|
||||
ctrl.isAdmin = isAdmin;
|
||||
var resourceControl = ctrl.resourceControl;
|
||||
|
||||
if (isAdmin) {
|
||||
if (resourceControl) {
|
||||
ctrl.formValues.Ownership = resourceControl.Ownership === 'private' ? 'restricted' : resourceControl.Ownership;
|
||||
} else {
|
||||
ctrl.formValues.Ownership = 'public';
|
||||
}
|
||||
} else {
|
||||
ctrl.formValues.Ownership = 'public';
|
||||
}
|
||||
|
||||
ResourceControlService.retrieveOwnershipDetails(resourceControl)
|
||||
.then(function success(data) {
|
||||
ctrl.authorizedUsers = data.authorizedUsers;
|
||||
ctrl.authorizedTeams = data.authorizedTeams;
|
||||
return ResourceControlService.retrieveUserPermissionsOnResource(userId, isAdmin, resourceControl);
|
||||
})
|
||||
.then(function success(data) {
|
||||
ctrl.state.canEditOwnership = data.isPartOfRestrictedUsers || data.isLeaderOfAnyRestrictedTeams;
|
||||
ctrl.state.canChangeOwnershipToTeam = data.isPartOfRestrictedUsers;
|
||||
|
||||
return $q.all({
|
||||
availableUsers: isAdmin ? UserService.users(false) : [],
|
||||
availableTeams: isAdmin || data.isPartOfRestrictedUsers ? UserService.userTeams(userId) : []
|
||||
});
|
||||
})
|
||||
.then(function success(data) {
|
||||
ctrl.availableUsers = data.availableUsers;
|
||||
angular.forEach(ctrl.availableUsers, function(user) {
|
||||
var found = _.find(ctrl.authorizedUsers, { Id: user.Id });
|
||||
if (found) {
|
||||
user.selected = true;
|
||||
}
|
||||
});
|
||||
ctrl.availableTeams = data.availableTeams;
|
||||
angular.forEach(data.availableTeams, function(team) {
|
||||
var found = _.find(ctrl.authorizedTeams, { Id: team.Id });
|
||||
if (found) {
|
||||
team.selected = true;
|
||||
}
|
||||
});
|
||||
if (data.availableTeams.length === 1) {
|
||||
ctrl.formValues.Ownership_Teams.push(data.availableTeams[0]);
|
||||
}
|
||||
ctrl.state.displayAccessControlPanel = true;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'Unable to retrieve access control information');
|
||||
})
|
||||
.finally(function final() {
|
||||
$('#loadingViewSpinner').hide();
|
||||
});
|
||||
}
|
||||
|
||||
initComponent();
|
||||
}]);
|
|
@ -4,25 +4,25 @@ angular.module('portainer.helpers')
|
|||
var helper = {};
|
||||
|
||||
helper.retrieveAuthorizedUsers = function(resourceControl, users) {
|
||||
var authorizedUserNames = [];
|
||||
var authorizedUsers = [];
|
||||
angular.forEach(resourceControl.UserAccesses, function(access) {
|
||||
var user = _.find(users, { Id: access.UserId });
|
||||
if (user) {
|
||||
authorizedUserNames.push(user);
|
||||
authorizedUsers.push(user);
|
||||
}
|
||||
});
|
||||
return authorizedUserNames;
|
||||
return authorizedUsers;
|
||||
};
|
||||
|
||||
helper.retrieveAuthorizedTeams = function(resourceControl, teams) {
|
||||
var authorizedTeamNames = [];
|
||||
var authorizedTeams = [];
|
||||
angular.forEach(resourceControl.TeamAccesses, function(access) {
|
||||
var team = _.find(teams, { Id: access.TeamId });
|
||||
if (team) {
|
||||
authorizedTeamNames.push(team);
|
||||
authorizedTeams.push(team);
|
||||
}
|
||||
});
|
||||
return authorizedTeamNames;
|
||||
return authorizedTeams;
|
||||
};
|
||||
|
||||
helper.isLeaderOfAnyRestrictedTeams = function(userMemberships, resourceControl) {
|
||||
|
|
|
@ -29,14 +29,14 @@ angular.module('portainer.services')
|
|||
};
|
||||
|
||||
service.applyResourceControl = function(resourceControlType, resourceIdentifier, userId, accessControlData, subResources) {
|
||||
if (!accessControlData.accessControlEnabled) {
|
||||
if (!accessControlData.AccessControlEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var authorizedUserIds = [];
|
||||
var authorizedTeamIds = [];
|
||||
var administratorsOnly = false;
|
||||
switch (accessControlData.ownership) {
|
||||
switch (accessControlData.Ownership) {
|
||||
case 'administrators':
|
||||
administratorsOnly = true;
|
||||
break;
|
||||
|
@ -44,10 +44,10 @@ angular.module('portainer.services')
|
|||
authorizedUserIds.push(userId);
|
||||
break;
|
||||
case 'restricted':
|
||||
angular.forEach(accessControlData.authorizedUsers, function(user) {
|
||||
angular.forEach(accessControlData.AuthorizedUsers, function(user) {
|
||||
authorizedUserIds.push(user.Id);
|
||||
});
|
||||
angular.forEach(accessControlData.authorizedTeams, function(team) {
|
||||
angular.forEach(accessControlData.AuthorizedTeams, function(team) {
|
||||
authorizedTeamIds.push(team.Id);
|
||||
});
|
||||
break;
|
||||
|
@ -83,9 +83,9 @@ angular.module('portainer.services')
|
|||
teams: resourceControl.TeamAccesses.length > 0 ? TeamService.teams() : []
|
||||
})
|
||||
.then(function success(data) {
|
||||
var authorizedUserNames = ResourceControlHelper.retrieveAuthorizedUsers(resourceControl, data.users);
|
||||
var authorizedTeamNames = ResourceControlHelper.retrieveAuthorizedTeams(resourceControl, data.teams);
|
||||
deferred.resolve({ authorizedUsers: authorizedUserNames, authorizedTeams: authorizedTeamNames });
|
||||
var authorizedUsers = ResourceControlHelper.retrieveAuthorizedUsers(resourceControl, data.users);
|
||||
var authorizedTeams = ResourceControlHelper.retrieveAuthorizedTeams(resourceControl, data.teams);
|
||||
deferred.resolve({ authorizedUsers: authorizedUsers, authorizedTeams: authorizedTeams });
|
||||
})
|
||||
.catch(function error(err) {
|
||||
deferred.reject({ msg: 'Unable to retrieve user and team information', err: err });
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
// ControllerDataPipeline is used to transfer data between multiple controllers.
|
||||
angular.module('portainer.services')
|
||||
.factory('ControllerDataPipeline', [function ControllerDataPipelineFactory() {
|
||||
'use strict';
|
||||
|
||||
var pipeline = {};
|
||||
|
||||
// accessControlData is used to manage the data required by the accessControlPanelController.
|
||||
var accessControlData = {};
|
||||
|
||||
pipeline.setAccessControlData = function (type, resourceId, resourceControl) {
|
||||
accessControlData.resourceType = type;
|
||||
accessControlData.resourceId = resourceId;
|
||||
accessControlData.resourceControl = resourceControl;
|
||||
};
|
||||
|
||||
pipeline.getAccessControlData = function() {
|
||||
return accessControlData;
|
||||
};
|
||||
|
||||
// accessControlFormData is used to manage the data available in the scope of the accessControlFormController.
|
||||
var accessControlFormData = {};
|
||||
|
||||
pipeline.setAccessControlFormData = function(accessControlEnabled, ownership, authorizedUsers, authorizedTeams) {
|
||||
accessControlFormData.accessControlEnabled = accessControlEnabled;
|
||||
accessControlFormData.ownership = ownership;
|
||||
accessControlFormData.authorizedUsers = authorizedUsers;
|
||||
accessControlFormData.authorizedTeams = authorizedTeams;
|
||||
};
|
||||
|
||||
pipeline.getAccessControlFormData = function() {
|
||||
return accessControlFormData;
|
||||
};
|
||||
|
||||
return pipeline;
|
||||
}]);
|
|
@ -5,16 +5,16 @@ angular.module('portainer.services')
|
|||
var validator = {};
|
||||
|
||||
validator.validateAccessControl = function(accessControlData, isAdmin) {
|
||||
if (!accessControlData.accessControlEnabled) {
|
||||
if (!accessControlData.AccessControlEnabled) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (isAdmin && accessControlData.ownership === 'restricted' &&
|
||||
accessControlData.authorizedUsers.length === 0 &&
|
||||
accessControlData.authorizedTeams.length === 0) {
|
||||
if (isAdmin && accessControlData.Ownership === 'restricted' &&
|
||||
accessControlData.AuthorizedUsers.length === 0 &&
|
||||
accessControlData.AuthorizedTeams.length === 0) {
|
||||
return 'You must specify at least one team or user.';
|
||||
} else if (!isAdmin && accessControlData.ownership === 'restricted' &&
|
||||
accessControlData.authorizedTeams.length === 0) {
|
||||
} else if (!isAdmin && accessControlData.Ownership === 'restricted' &&
|
||||
accessControlData.AuthorizedTeams.length === 0) {
|
||||
return 'You must specify at least a team.';
|
||||
}
|
||||
return '';
|
||||
|
|
14
gruntfile.js
14
gruntfile.js
|
@ -29,7 +29,7 @@ module.exports = function (grunt) {
|
|||
grunt.registerTask('after-copy', [
|
||||
'filerev',
|
||||
'usemin',
|
||||
'clean:tmp'
|
||||
'clean:tmp'
|
||||
]);
|
||||
grunt.registerTask('build-webapp', [
|
||||
'config:prod',
|
||||
|
@ -37,7 +37,7 @@ module.exports = function (grunt) {
|
|||
'before-copy',
|
||||
'copy:assets',
|
||||
'after-copy'
|
||||
]);
|
||||
]);
|
||||
grunt.registerTask('build', [
|
||||
'config:dev',
|
||||
'clean:app',
|
||||
|
@ -52,7 +52,7 @@ module.exports = function (grunt) {
|
|||
]);
|
||||
grunt.task.registerTask('release', 'release:<platform>:<arch>', function(p, a) {
|
||||
grunt.task.run(['config:prod', 'clean:all', 'shell:buildBinary:'+p+':'+a, 'before-copy', 'copy:assets', 'after-copy' ]);
|
||||
});
|
||||
});
|
||||
grunt.registerTask('lint', ['eslint']);
|
||||
grunt.registerTask('run-dev', ['build', 'shell:run', 'watch:build']);
|
||||
grunt.registerTask('clear', ['clean:app']);
|
||||
|
@ -69,10 +69,10 @@ module.exports = function (grunt) {
|
|||
js: ['app/**/*.js', '!app/**/*.spec.js'],
|
||||
jsTpl: ['<%= distdir %>/templates/**/*.js'],
|
||||
jsVendor: [
|
||||
'bower_components/angular-multi-select/isteven-multi-select.js',
|
||||
'bower_components/bootbox.js/bootbox.js',
|
||||
'bower_components/jquery/dist/jquery.min.js',
|
||||
'bower_components/bootstrap/dist/js/bootstrap.min.js',
|
||||
'bower_components/angular-multi-select/isteven-multi-select.js',
|
||||
'bower_components/bootbox.js/bootbox.js',
|
||||
'bower_components/Chart.js/Chart.min.js',
|
||||
'bower_components/filesize/lib/filesize.min.js',
|
||||
'bower_components/lodash/dist/lodash.min.js',
|
||||
|
@ -86,9 +86,9 @@ module.exports = function (grunt) {
|
|||
tpl: ['app/components/**/*.html', 'app/directives/**/*.html'],
|
||||
css: ['assets/css/app.css'],
|
||||
cssVendor: [
|
||||
'bower_components/bootstrap/dist/css/bootstrap.css',
|
||||
'bower_components/angular-multi-select/isteven-multi-select.css',
|
||||
'bower_components/angular-ui-select/dist/select.min.css',
|
||||
'bower_components/bootstrap/dist/css/bootstrap.css',
|
||||
'bower_components/font-awesome/css/font-awesome.min.css',
|
||||
'bower_components/rdash-ui/dist/css/rdash.min.css',
|
||||
'bower_components/toastr/toastr.min.css',
|
||||
|
@ -248,7 +248,7 @@ module.exports = function (grunt) {
|
|||
return 'build/build_in_container.sh ' + p + ' ' + a;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
run: {
|
||||
command: [
|
||||
'docker rm -f portainer',
|
||||
|
|
Loading…
Reference in New Issue