mirror of
https://github.com/portainer/portainer.git
synced 2025-08-08 15:25:22 +02:00
feat(endpoint): relocate docker security settings (#4657)
* feat(endpoint): migrate security settings to endpoint * feat(endpoint): check for specific endpoint settings * feat(endpoint): check security settings * feat(docker): add config page * feat(endpoint): save settings page * feat(endpoints): disable features when not agent * feat(sidebar): hide docker settings for regular user * fix(docker): small fixes in configs * fix(volumes): hide browse button for non admins * refactor(docker): introduce switch component * refactor(components/switch): seprate label from switch * feat(app/components): align switch label * refactor(app/components): move switch css * fix(docker/settings): add ngijnect * feat(endpoints): set default security values * style(portainer): sort types * fix(endpoint): rename security heading * fix(endpoints): update endpoints settings
This commit is contained in:
parent
e401724d43
commit
46dec01fe3
46 changed files with 714 additions and 461 deletions
|
@ -0,0 +1,52 @@
|
|||
/* switch box */
|
||||
|
||||
.switch {
|
||||
--switch-size: 24px;
|
||||
}
|
||||
|
||||
.switch.small {
|
||||
--switch-size: 12px;
|
||||
}
|
||||
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.switch i,
|
||||
.bootbox-form .checkbox i {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
padding-right: var(--switch-size);
|
||||
transition: all ease 0.2s;
|
||||
-webkit-transition: all ease 0.2s;
|
||||
-moz-transition: all ease 0.2s;
|
||||
-o-transition: all ease 0.2s;
|
||||
border-radius: var(--switch-size);
|
||||
box-shadow: inset 0 0 1px 1px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.switch i:before,
|
||||
.bootbox-form .checkbox i:before {
|
||||
display: block;
|
||||
content: '';
|
||||
width: var(--switch-size);
|
||||
height: var(--switch-size);
|
||||
border-radius: var(--switch-size);
|
||||
background: white;
|
||||
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.switch :checked + i,
|
||||
.bootbox-form .checkbox :checked ~ i {
|
||||
padding-right: 0;
|
||||
padding-left: var(--switch-size);
|
||||
-webkit-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 40px #337ab7;
|
||||
-moz-box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 40px #337ab7;
|
||||
box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.5), inset 0 0 40px #337ab7;
|
||||
}
|
||||
|
||||
.switch :disabled + i {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<label style="display: flex; align-items: center; margin: 0;">
|
||||
<span for="toggle_{{::$ctrl.name}}" class="control-label text-left space-right" ng-class="$ctrl.labelClass" style="padding: 0;">
|
||||
{{::$ctrl.label}}
|
||||
<portainer-tooltip ng-if="$ctrl.tooltip" position="bottom" message="{{::$ctrl.tooltip}}"></portainer-tooltip>
|
||||
</span>
|
||||
<por-switch
|
||||
class-name="space-right"
|
||||
name="toggle_{{::$ctrl.name}}"
|
||||
id="toggle_{{::$ctrl.name}}"
|
||||
ng-model="$ctrl.ngModel"
|
||||
disabled="$ctrl.disabled"
|
||||
on-change="($ctrl.onChange)"
|
||||
></por-switch>
|
||||
</label>
|
|
@ -0,0 +1,18 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import './por-switch-field.css';
|
||||
|
||||
export const porSwitchField = {
|
||||
templateUrl: './por-switch-field.html',
|
||||
bindings: {
|
||||
tooltip: '@',
|
||||
ngModel: '=',
|
||||
label: '@',
|
||||
name: '@',
|
||||
labelClass: '@',
|
||||
disabled: '<',
|
||||
onChange: '<',
|
||||
},
|
||||
};
|
||||
|
||||
angular.module('portainer.app').component('porSwitchField', porSwitchField);
|
|
@ -0,0 +1,3 @@
|
|||
<label class="switch" ng-class="$ctrl.className" style="margin-bottom: 0;">
|
||||
<input type="checkbox" name="{{::$ctrl.name}}" id="{{::$ctrl.id}}" ng-model="$ctrl.ngModel" ng-disabled="$ctrl.disabled" ng-change="$ctrl.onChange($ctrl.ngModel)" /><i></i>
|
||||
</label>
|
15
app/portainer/components/forms/por-switch/por-switch.js
Normal file
15
app/portainer/components/forms/por-switch/por-switch.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import angular from 'angular';
|
||||
|
||||
const porSwitch = {
|
||||
templateUrl: './por-switch.html',
|
||||
bindings: {
|
||||
ngModel: '=',
|
||||
id: '@',
|
||||
className: '@',
|
||||
name: '@',
|
||||
disabled: '<',
|
||||
onChange: '<',
|
||||
},
|
||||
};
|
||||
|
||||
angular.module('portainer.app').component('porSwitch', porSwitch);
|
|
@ -4,16 +4,8 @@ export function SettingsViewModel(data) {
|
|||
this.AuthenticationMethod = data.AuthenticationMethod;
|
||||
this.LDAPSettings = data.LDAPSettings;
|
||||
this.OAuthSettings = new OAuthSettingsViewModel(data.OAuthSettings);
|
||||
this.AllowBindMountsForRegularUsers = data.AllowBindMountsForRegularUsers;
|
||||
this.AllowPrivilegedModeForRegularUsers = data.AllowPrivilegedModeForRegularUsers;
|
||||
this.AllowVolumeBrowserForRegularUsers = data.AllowVolumeBrowserForRegularUsers;
|
||||
this.AllowHostNamespaceForRegularUsers = data.AllowHostNamespaceForRegularUsers;
|
||||
this.AllowDeviceMappingForRegularUsers = data.AllowDeviceMappingForRegularUsers;
|
||||
this.AllowStackManagementForRegularUsers = data.AllowStackManagementForRegularUsers;
|
||||
this.AllowContainerCapabilitiesForRegularUsers = data.AllowContainerCapabilitiesForRegularUsers;
|
||||
this.SnapshotInterval = data.SnapshotInterval;
|
||||
this.TemplatesURL = data.TemplatesURL;
|
||||
this.EnableHostManagementFeatures = data.EnableHostManagementFeatures;
|
||||
this.EdgeAgentCheckinInterval = data.EdgeAgentCheckinInterval;
|
||||
this.EnableEdgeComputeFeatures = data.EnableEdgeComputeFeatures;
|
||||
this.UserSessionTimeout = data.UserSessionTimeout;
|
||||
|
@ -21,15 +13,7 @@ export function SettingsViewModel(data) {
|
|||
}
|
||||
|
||||
export function PublicSettingsViewModel(settings) {
|
||||
this.AllowBindMountsForRegularUsers = settings.AllowBindMountsForRegularUsers;
|
||||
this.AllowPrivilegedModeForRegularUsers = settings.AllowPrivilegedModeForRegularUsers;
|
||||
this.AllowVolumeBrowserForRegularUsers = settings.AllowVolumeBrowserForRegularUsers;
|
||||
this.AllowDeviceMappingForRegularUsers = settings.AllowDeviceMappingForRegularUsers;
|
||||
this.AllowStackManagementForRegularUsers = settings.AllowStackManagementForRegularUsers;
|
||||
this.AllowContainerCapabilitiesForRegularUsers = settings.AllowContainerCapabilitiesForRegularUsers;
|
||||
this.AllowHostNamespaceForRegularUsers = settings.AllowHostNamespaceForRegularUsers;
|
||||
this.AuthenticationMethod = settings.AuthenticationMethod;
|
||||
this.EnableHostManagementFeatures = settings.EnableHostManagementFeatures;
|
||||
this.EnableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures;
|
||||
this.LogoURL = settings.LogoURL;
|
||||
this.OAuthLoginURI = settings.OAuthLoginURI;
|
||||
|
|
|
@ -21,6 +21,7 @@ angular.module('portainer.app').factory('Endpoints', [
|
|||
snapshots: { method: 'POST', params: { action: 'snapshot' } },
|
||||
snapshot: { method: 'POST', params: { id: '@id', action: 'snapshot' } },
|
||||
status: { method: 'GET', params: { id: '@id', action: 'status' } },
|
||||
updateSecuritySettings: { method: 'PUT', params: { id: '@id', action: 'settings' } },
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
|
@ -6,7 +6,9 @@ angular.module('portainer.app').factory('EndpointService', [
|
|||
'FileUploadService',
|
||||
function EndpointServiceFactory($q, Endpoints, FileUploadService) {
|
||||
'use strict';
|
||||
var service = {};
|
||||
var service = {
|
||||
updateSecuritySettings,
|
||||
};
|
||||
|
||||
service.endpoint = function (endpointID) {
|
||||
return Endpoints.get({ id: endpointID }).$promise;
|
||||
|
@ -146,5 +148,9 @@ angular.module('portainer.app').factory('EndpointService', [
|
|||
};
|
||||
|
||||
return service;
|
||||
|
||||
function updateSecuritySettings(id, securitySettings) {
|
||||
return Endpoints.updateSecuritySettings({ id }, securitySettings).$promise;
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -72,51 +72,11 @@ angular.module('portainer.app').factory('StateManager', [
|
|||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateEnableHostManagementFeatures = function (enableHostManagementFeatures) {
|
||||
state.application.enableHostManagementFeatures = enableHostManagementFeatures;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateEnableVolumeBrowserForNonAdminUsers = function (enableVolumeBrowserForNonAdminUsers) {
|
||||
state.application.enableVolumeBrowserForNonAdminUsers = enableVolumeBrowserForNonAdminUsers;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateEnableEdgeComputeFeatures = function updateEnableEdgeComputeFeatures(enableEdgeComputeFeatures) {
|
||||
state.application.enableEdgeComputeFeatures = enableEdgeComputeFeatures;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateAllowHostNamespaceForRegularUsers = function (allowHostNamespaceForRegularUsers) {
|
||||
state.application.allowHostNamespaceForRegularUsers = allowHostNamespaceForRegularUsers;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateAllowDeviceMappingForRegularUsers = function updateAllowDeviceMappingForRegularUsers(allowDeviceMappingForRegularUsers) {
|
||||
state.application.allowDeviceMappingForRegularUsers = allowDeviceMappingForRegularUsers;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateAllowStackManagementForRegularUsers = function updateAllowStackManagementForRegularUsers(allowStackManagementForRegularUsers) {
|
||||
state.application.allowStackManagementForRegularUsers = allowStackManagementForRegularUsers;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateAllowContainerCapabilitiesForRegularUsers = function updateAllowContainerCapabilitiesForRegularUsers(allowContainerCapabilitiesForRegularUsers) {
|
||||
state.application.allowContainerCapabilitiesForRegularUsers = allowContainerCapabilitiesForRegularUsers;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateAllowBindMountsForRegularUsers = function updateAllowBindMountsForRegularUsers(allowBindMountsForRegularUsers) {
|
||||
state.application.allowBindMountsForRegularUsers = allowBindMountsForRegularUsers;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateAllowPrivilegedModeForRegularUsers = function (AllowPrivilegedModeForRegularUsers) {
|
||||
state.application.allowPrivilegedModeForRegularUsers = AllowPrivilegedModeForRegularUsers;
|
||||
LocalStorage.storeApplicationState(state.application);
|
||||
};
|
||||
|
||||
manager.updateEnableTelemetry = function updateEnableTelemetry(enableTelemetry) {
|
||||
state.application.enableTelemetry = enableTelemetry;
|
||||
$analytics.setOptOut(!enableTelemetry);
|
||||
|
@ -128,15 +88,7 @@ angular.module('portainer.app').factory('StateManager', [
|
|||
state.application.enableTelemetry = settings.EnableTelemetry;
|
||||
state.application.logo = settings.LogoURL;
|
||||
state.application.snapshotInterval = settings.SnapshotInterval;
|
||||
state.application.enableHostManagementFeatures = settings.EnableHostManagementFeatures;
|
||||
state.application.enableVolumeBrowserForNonAdminUsers = settings.AllowVolumeBrowserForRegularUsers;
|
||||
state.application.enableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures;
|
||||
state.application.allowDeviceMappingForRegularUsers = settings.AllowDeviceMappingForRegularUsers;
|
||||
state.application.allowStackManagementForRegularUsers = settings.AllowStackManagementForRegularUsers;
|
||||
state.application.allowContainerCapabilitiesForRegularUsers = settings.AllowContainerCapabilitiesForRegularUsers;
|
||||
state.application.allowBindMountsForRegularUsers = settings.AllowBindMountsForRegularUsers;
|
||||
state.application.allowPrivilegedModeForRegularUsers = settings.AllowPrivilegedModeForRegularUsers;
|
||||
state.application.allowHostNamespaceForRegularUsers = settings.AllowHostNamespaceForRegularUsers;
|
||||
state.application.validity = moment().unix();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,100 +76,7 @@
|
|||
</div>
|
||||
<!-- !templates -->
|
||||
<!-- host-filesystem -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Host and Filesystem
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_enableHostManagementFeatures" class="control-label text-left">
|
||||
Enable host management features
|
||||
<portainer-tooltip position="bottom" message="Enable host management features: host system browsing and advanced host details."></portainer-tooltip>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" name="toggle_enableHostManagementFeatures" ng-model="formValues.enableHostManagementFeatures" /><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_allowvolumebrowser" class="control-label text-left">
|
||||
Enable volume management for non-administrators
|
||||
<portainer-tooltip position="bottom" message="When enabled, regular users will be able to use Portainer volume management features."></portainer-tooltip>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="toggle_allowvolumebrowser" ng-model="formValues.enableVolumeBrowser" /><i></i> </label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !host-filesystem -->
|
||||
<!-- security -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Docker Endpoint Security Options
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_allowbindmounts" class="control-label text-left">
|
||||
Disable bind mounts for non-administrators
|
||||
<portainer-tooltip position="bottom" message="When enabled, regular users will not be able to use bind mounts when creating containers."></portainer-tooltip>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="toggle_allowbindmounts" ng-model="formValues.restrictBindMounts" /><i></i> </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_allowbindmounts" class="control-label text-left">
|
||||
Disable privileged mode for non-administrators
|
||||
<portainer-tooltip position="bottom" message="When enabled, regular users will not be able to use privileged mode when creating containers."></portainer-tooltip>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="toggle_allowbindmounts" ng-model="formValues.restrictPrivilegedMode" /><i></i> </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_allowHostNamespaceForRegularUsers" class="control-label text-left">
|
||||
Disable the use of host PID 1 for non-administrators
|
||||
<portainer-tooltip position="bottom" message="Prevent users from accessing the host filesystem through the host PID namespace."></portainer-tooltip>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" name="toggle_allowHostNamespaceForRegularUsers" ng-model="formValues.restrictHostNamespaceForRegularUsers" /><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_disableStackManagementForRegularUsers" class="control-label text-left">
|
||||
Disable the use of Stacks for non-administrators
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" name="toggle_disableStackManagementForRegularUsers" ng-model="formValues.disableStackManagementForRegularUsers" /><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_disableDeviceMappingForRegularUsers" class="control-label text-left">
|
||||
Disable device mappings for non-administrators
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" name="toggle_disableDeviceMappingForRegularUsers" ng-model="formValues.disableDeviceMappingForRegularUsers" /><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="toggle_disableContainerCapabilitiesForRegularUsers" class="control-label text-left">
|
||||
Disable container capabilities for non-administrators
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" name="toggle_disableContainerCapabilitiesForRegularUsers" ng-model="formValues.disableContainerCapabilitiesForRegularUsers" /><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="isContainerEditDisabled()">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Note: The recreate/duplicate/edit feature is currently disabled (for non-admin users) by one or more security settings.
|
||||
</span>
|
||||
</div>
|
||||
<!-- !security -->
|
||||
<!-- edge -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Edge Compute
|
||||
|
|
|
@ -25,33 +25,12 @@ angular.module('portainer.app').controller('SettingsController', [
|
|||
|
||||
$scope.formValues = {
|
||||
customLogo: false,
|
||||
restrictBindMounts: false,
|
||||
restrictPrivilegedMode: false,
|
||||
labelName: '',
|
||||
labelValue: '',
|
||||
enableHostManagementFeatures: false,
|
||||
enableVolumeBrowser: false,
|
||||
enableEdgeComputeFeatures: false,
|
||||
restrictHostNamespaceForRegularUsers: false,
|
||||
allowDeviceMappingForRegularUsers: false,
|
||||
allowStackManagementForRegularUsers: false,
|
||||
disableContainerCapabilitiesForRegularUsers: false,
|
||||
enableTelemetry: false,
|
||||
};
|
||||
|
||||
$scope.isContainerEditDisabled = function isContainerEditDisabled() {
|
||||
const {
|
||||
restrictBindMounts,
|
||||
restrictHostNamespaceForRegularUsers,
|
||||
restrictPrivilegedMode,
|
||||
disableDeviceMappingForRegularUsers,
|
||||
disableContainerCapabilitiesForRegularUsers,
|
||||
} = this.formValues;
|
||||
return (
|
||||
restrictBindMounts || restrictHostNamespaceForRegularUsers || restrictPrivilegedMode || disableDeviceMappingForRegularUsers || disableContainerCapabilitiesForRegularUsers
|
||||
);
|
||||
};
|
||||
|
||||
$scope.removeFilteredContainerLabel = function (index) {
|
||||
var settings = $scope.settings;
|
||||
settings.BlackListedLabels.splice(index, 1);
|
||||
|
@ -77,15 +56,7 @@ angular.module('portainer.app').controller('SettingsController', [
|
|||
settings.LogoURL = '';
|
||||
}
|
||||
|
||||
settings.AllowBindMountsForRegularUsers = !$scope.formValues.restrictBindMounts;
|
||||
settings.AllowPrivilegedModeForRegularUsers = !$scope.formValues.restrictPrivilegedMode;
|
||||
settings.AllowVolumeBrowserForRegularUsers = $scope.formValues.enableVolumeBrowser;
|
||||
settings.EnableHostManagementFeatures = $scope.formValues.enableHostManagementFeatures;
|
||||
settings.EnableEdgeComputeFeatures = $scope.formValues.enableEdgeComputeFeatures;
|
||||
settings.AllowHostNamespaceForRegularUsers = !$scope.formValues.restrictHostNamespaceForRegularUsers;
|
||||
settings.AllowDeviceMappingForRegularUsers = !$scope.formValues.disableDeviceMappingForRegularUsers;
|
||||
settings.AllowStackManagementForRegularUsers = !$scope.formValues.disableStackManagementForRegularUsers;
|
||||
settings.AllowContainerCapabilitiesForRegularUsers = !$scope.formValues.disableContainerCapabilitiesForRegularUsers;
|
||||
settings.EnableTelemetry = $scope.formValues.enableTelemetry;
|
||||
|
||||
$scope.state.actionInProgress = true;
|
||||
|
@ -98,15 +69,7 @@ angular.module('portainer.app').controller('SettingsController', [
|
|||
Notifications.success('Settings updated');
|
||||
StateManager.updateLogo(settings.LogoURL);
|
||||
StateManager.updateSnapshotInterval(settings.SnapshotInterval);
|
||||
StateManager.updateEnableHostManagementFeatures(settings.EnableHostManagementFeatures);
|
||||
StateManager.updateEnableVolumeBrowserForNonAdminUsers(settings.AllowVolumeBrowserForRegularUsers);
|
||||
StateManager.updateAllowHostNamespaceForRegularUsers(settings.AllowHostNamespaceForRegularUsers);
|
||||
StateManager.updateEnableEdgeComputeFeatures(settings.EnableEdgeComputeFeatures);
|
||||
StateManager.updateAllowDeviceMappingForRegularUsers(settings.AllowDeviceMappingForRegularUsers);
|
||||
StateManager.updateAllowStackManagementForRegularUsers(settings.AllowStackManagementForRegularUsers);
|
||||
StateManager.updateAllowContainerCapabilitiesForRegularUsers(settings.AllowContainerCapabilitiesForRegularUsers);
|
||||
StateManager.updateAllowPrivilegedModeForRegularUsers(settings.AllowPrivilegedModeForRegularUsers);
|
||||
StateManager.updateAllowBindMountsForRegularUsers(settings.AllowBindMountsForRegularUsers);
|
||||
StateManager.updateEnableTelemetry(settings.EnableTelemetry);
|
||||
$state.reload();
|
||||
})
|
||||
|
@ -127,15 +90,7 @@ angular.module('portainer.app').controller('SettingsController', [
|
|||
if (settings.LogoURL !== '') {
|
||||
$scope.formValues.customLogo = true;
|
||||
}
|
||||
$scope.formValues.restrictBindMounts = !settings.AllowBindMountsForRegularUsers;
|
||||
$scope.formValues.restrictPrivilegedMode = !settings.AllowPrivilegedModeForRegularUsers;
|
||||
$scope.formValues.enableVolumeBrowser = settings.AllowVolumeBrowserForRegularUsers;
|
||||
$scope.formValues.enableHostManagementFeatures = settings.EnableHostManagementFeatures;
|
||||
$scope.formValues.enableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures;
|
||||
$scope.formValues.restrictHostNamespaceForRegularUsers = !settings.AllowHostNamespaceForRegularUsers;
|
||||
$scope.formValues.disableDeviceMappingForRegularUsers = !settings.AllowDeviceMappingForRegularUsers;
|
||||
$scope.formValues.disableStackManagementForRegularUsers = !settings.AllowStackManagementForRegularUsers;
|
||||
$scope.formValues.disableContainerCapabilitiesForRegularUsers = !settings.AllowContainerCapabilitiesForRegularUsers;
|
||||
$scope.formValues.enableTelemetry = settings.EnableTelemetry;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
|
|
|
@ -46,9 +46,17 @@ angular.module('portainer.app').controller('SidebarController', [
|
|||
|
||||
async function shouldShowStacks() {
|
||||
const isAdmin = Authentication.isAdmin();
|
||||
const { allowStackManagementForRegularUsers } = $scope.applicationState.application;
|
||||
|
||||
return isAdmin || allowStackManagementForRegularUsers;
|
||||
if (isAdmin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const endpoint = EndpointProvider.currentEndpoint();
|
||||
if (!endpoint || !endpoint.SecuritySettings) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return endpoint.SecuritySettings.allowStackManagementForRegularUsers;
|
||||
}
|
||||
|
||||
$transitions.onEnter({}, async () => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
angular.module('portainer.app').controller('StacksController', StacksController);
|
||||
|
||||
/* @ngInject */
|
||||
function StacksController($scope, $state, Notifications, StackService, ModalService, EndpointProvider, Authentication, StateManager) {
|
||||
function StacksController($scope, $state, Notifications, StackService, ModalService, EndpointProvider, Authentication, endpoint) {
|
||||
$scope.removeAction = function (selectedItems) {
|
||||
ModalService.confirmDeletion('Do you want to remove the selected stack(s)? Associated services will be removed as well.', function onConfirm(confirmed) {
|
||||
if (!confirmed) {
|
||||
|
@ -55,8 +55,7 @@ function StacksController($scope, $state, Notifications, StackService, ModalServ
|
|||
}
|
||||
|
||||
async function loadCreateEnabled() {
|
||||
const appState = StateManager.getState().application;
|
||||
return appState.allowStackManagementForRegularUsers || Authentication.isAdmin();
|
||||
return endpoint.SecuritySettings.allowStackManagementForRegularUsers || Authentication.isAdmin();
|
||||
}
|
||||
|
||||
async function initView() {
|
||||
|
|
|
@ -16,8 +16,8 @@ angular.module('portainer.app').controller('TemplatesController', [
|
|||
'ResourceControlService',
|
||||
'Authentication',
|
||||
'FormValidator',
|
||||
'SettingsService',
|
||||
'StackService',
|
||||
'endpoint',
|
||||
function (
|
||||
$scope,
|
||||
$q,
|
||||
|
@ -33,8 +33,8 @@ angular.module('portainer.app').controller('TemplatesController', [
|
|||
ResourceControlService,
|
||||
Authentication,
|
||||
FormValidator,
|
||||
SettingsService,
|
||||
StackService
|
||||
StackService,
|
||||
endpoint
|
||||
) {
|
||||
$scope.state = {
|
||||
selectedTemplate: null,
|
||||
|
@ -263,7 +263,6 @@ angular.module('portainer.app').controller('TemplatesController', [
|
|||
false,
|
||||
endpointMode.provider === 'DOCKER_SWARM_MODE' && apiVersion >= 1.25
|
||||
),
|
||||
settings: SettingsService.publicSettings(),
|
||||
})
|
||||
.then(function success(data) {
|
||||
var templates = data.templates;
|
||||
|
@ -271,8 +270,7 @@ angular.module('portainer.app').controller('TemplatesController', [
|
|||
$scope.availableVolumes = _.orderBy(data.volumes.Volumes, [(volume) => volume.Name.toLowerCase()], ['asc']);
|
||||
var networks = data.networks;
|
||||
$scope.availableNetworks = networks;
|
||||
var settings = data.settings;
|
||||
$scope.allowBindMounts = settings.AllowBindMountsForRegularUsers;
|
||||
$scope.allowBindMounts = endpoint.SecuritySettings.allowBindMountsForRegularUsers;
|
||||
})
|
||||
.catch(function error(err) {
|
||||
$scope.templates = [];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue