mirror of https://github.com/portainer/portainer
feat(ce): fix small issues for Highlight Business Edition feature (#6043)
* feat(logs): added orange border to export button. * fix(ldap): fixed connectivity check radio button alignment issue * fix(be-feature): added box shadow to limited feature border * fix(be-feature): fixed hide internal auth toggle issue. * feat(ldap): added isLimitedFeatureSelfContained config to ldap-custom-admin-group and test-login components * feat(auth): moved save settings button in auth page to a component. * feat(oauth): use saveSettingsButton component in oauth * feat(oauth): use saveSettingsButton component in internal auth * feat(oauth): use saveSettingsButton component in MS active directory auth * feat(oauth): use saveSettingsButton component in ldap auth * feat(auth): added new component to index.js * removed css inline styles. * feat(ad): added disable check method to ad auth. * feat(ldap): moved save settings disable method to parent component * removed inline styles. * fix(ldap): fixed test login misalignment issue * fix(ldap): pass isLdapFormValid function from page component * fix(ldap): made the toggle button in custom admin group orange when it's limited to CE. * fix(auth): fixed save setting button in Microsoft Active Directory auth * fix(ldap): made the assign admin toggle bright orangepull/6167/head
parent
18c323185e
commit
3f31d4b00b
|
@ -845,6 +845,54 @@ json-tree .branch-preview {
|
|||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.m-l-5 {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.m-l-20 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.m-l-30 {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.m-r-2 {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.m-r-5 {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.m-t-10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.m-t-10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.m-b-10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.no-margin {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.no-border {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dispay-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.text-wrap {
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
|
|
|
@ -6,15 +6,22 @@
|
|||
border-color: var(--border-form-control-color);
|
||||
}
|
||||
|
||||
button.limited-be {
|
||||
button.limited-be,
|
||||
button[disabled].limited-be.oauth-save-settings-button {
|
||||
background-color: var(--BE-only);
|
||||
border-color: var(--BE-only);
|
||||
}
|
||||
|
||||
button.limited-be.oauth-save-settings-button {
|
||||
background-color: var(--blue-2);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
ng-form.limited-be,
|
||||
form.limited-be,
|
||||
div.limited-be {
|
||||
border: solid 1px var(--BE-only);
|
||||
box-shadow: var(--shadow-boxselector-color);
|
||||
padding: 10px;
|
||||
pointer-events: none;
|
||||
touch-action: none;
|
||||
|
|
|
@ -6,6 +6,8 @@ angular.module('portainer.oauth').component('oauthSettings', {
|
|||
bindings: {
|
||||
settings: '=',
|
||||
teams: '<',
|
||||
onSaveSettings: '<',
|
||||
saveButtonState: '<',
|
||||
},
|
||||
controller,
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@ export default class OAuthSettingsController {
|
|||
this.featureService = featureService;
|
||||
|
||||
this.limitedFeature = HIDE_INTERNAL_AUTH;
|
||||
this.limitedFeatureClass = 'limited-be';
|
||||
|
||||
this.state = {
|
||||
provider: 'custom',
|
||||
|
@ -61,7 +62,7 @@ export default class OAuthSettingsController {
|
|||
}
|
||||
|
||||
updateSSO() {
|
||||
this.settings.HideInternalAuth = this.settings.SSO;
|
||||
this.settings.HideInternalAuth = this.featureService.isLimitedToBE(this.limitedFeature) ? false : this.settings.SSO;
|
||||
}
|
||||
|
||||
addTeamMembershipMapping() {
|
||||
|
@ -72,6 +73,20 @@ export default class OAuthSettingsController {
|
|||
this.settings.TeamMemberships.OAuthClaimMappings.splice(index, 1);
|
||||
}
|
||||
|
||||
isOAuthTeamMembershipFormValid() {
|
||||
if (this.settings.OAuthAutoMapTeamMemberships && this.settings.TeamMemberships) {
|
||||
if (!this.settings.TeamMemberships.OAuthClaimName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasInvalidMapping = this.settings.TeamMemberships.OAuthClaimMappings.some((m) => !(m.ClaimValRegex && m.Team));
|
||||
if (hasInvalidMapping) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.isLimitedToBE = this.featureService.isLimitedToBE(this.limitedFeature);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ng-form name="$ctrl.oauthSettingsForm">
|
||||
<ng-form name="oauthSettingsForm">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Single Sign-On
|
||||
</div>
|
||||
|
@ -379,4 +379,12 @@
|
|||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<save-auth-settings-button
|
||||
on-save-settings="($ctrl.onSaveSettings)"
|
||||
save-button-state="($ctrl.saveButtonState)"
|
||||
save-button-disabled="!$ctrl.isOAuthTeamMembershipFormValid() || oauthSettingsForm.$invalid"
|
||||
limited-feature-id="$ctrl.limitedFeature"
|
||||
limited-feature-class="$ctrl.limitedFeatureClass"
|
||||
class-name="'oauth-save-settings-button'"
|
||||
></save-auth-settings-button>
|
||||
</ng-form>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import angular from 'angular';
|
||||
|
||||
import ldapModule from './ldap';
|
||||
|
||||
import { autoUserProvisionToggle } from './auto-user-provision-toggle';
|
||||
import { saveAuthSettingsButton } from './save-auth-settings-button';
|
||||
import { internalAuth } from './internal-auth';
|
||||
|
||||
export default angular
|
||||
.module('portainer.settings.authentication', [ldapModule])
|
||||
|
||||
.component('internalAuth', internalAuth)
|
||||
.component('saveAuthSettingsButton', saveAuthSettingsButton)
|
||||
.component('autoUserProvisionToggle', autoUserProvisionToggle).name;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export const internalAuth = {
|
||||
templateUrl: './internal-auth.html',
|
||||
bindings: {
|
||||
onSaveSettings: '<',
|
||||
saveButtonState: '<',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
<div class="col-sm-12 form-section-title">
|
||||
Information
|
||||
</div>
|
||||
<div class="form-group col-sm-12 text-muted small">
|
||||
When using internal authentication, Portainer will encrypt user passwords and store credentials locally.
|
||||
</div>
|
||||
|
||||
<save-auth-settings-button on-save-settings="($ctrl.onSaveSettings)" save-button-state="($ctrl.saveButtonState)"></save-auth-settings-button>
|
|
@ -3,8 +3,9 @@ import { HIDE_INTERNAL_AUTH } from '@/portainer/feature-flags/feature-ids';
|
|||
|
||||
export default class AdSettingsController {
|
||||
/* @ngInject */
|
||||
constructor(LDAPService) {
|
||||
constructor(LDAPService, featureService) {
|
||||
this.LDAPService = LDAPService;
|
||||
this.featureService = featureService;
|
||||
|
||||
this.domainSuffix = '';
|
||||
this.limitedFeatureId = HIDE_INTERNAL_AUTH;
|
||||
|
@ -55,6 +56,10 @@ export default class AdSettingsController {
|
|||
this.settings.URLs.splice(index, 1);
|
||||
}
|
||||
|
||||
isSaveSettingButtonDisabled() {
|
||||
return this.featureService.isLimitedToBE(this.limitedFeatureId) || !this.isLdapFormValid();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.tlscaCert = this.settings.TLSCACert;
|
||||
this.parseDomainName(this.settings.ReaderDN);
|
||||
|
|
|
@ -160,7 +160,14 @@
|
|||
selected-admin-groups="$ctrl.selectedAdminGroups"
|
||||
default-admin-group-search-filter="'(objectClass=groupOfNames)'"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
is-limited-feature-self-contained="false"
|
||||
></ldap-custom-admin-group>
|
||||
|
||||
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId"></ldap-settings-test-login>
|
||||
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId" is-limited-feature-self-contained="false"></ldap-settings-test-login>
|
||||
<save-auth-settings-button
|
||||
on-save-settings="($ctrl.onSaveSettings)"
|
||||
save-button-state="($ctrl.saveButtonState)"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
save-button-disabled="($ctrl.isSaveSettingButtonDisabled())"
|
||||
></save-auth-settings-button>
|
||||
</ng-form>
|
||||
|
|
|
@ -8,5 +8,8 @@ export const adSettings = {
|
|||
tlscaCert: '=',
|
||||
state: '=',
|
||||
connectivityCheck: '<',
|
||||
onSaveSettings: '<',
|
||||
saveButtonState: '<',
|
||||
isLdapFormValid: '&?',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<div class="form-group">
|
||||
<label for="ldap_password" class="col-sm-3 control-label text-left">
|
||||
<label for="ldap_password" class="col-sm-3 col-lg-2 control-label text-left">
|
||||
Connectivity check
|
||||
<i class="fa fa-check green-icon" style="margin-left: 5px;" ng-if="$ctrl.state.successfulConnectivityCheck"></i>
|
||||
<i class="fa fa-times red-icon" style="margin-left: 5px;" ng-if="$ctrl.state.failedConnectivityCheck"></i>
|
||||
<i class="fa fa-check green-icon m-l-5" ng-if="$ctrl.state.successfulConnectivityCheck"></i>
|
||||
<i class="fa fa-times red-icon m-l-5" ng-if="$ctrl.state.failedConnectivityCheck"></i>
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="col-sm-9 col-lg-10">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import './ldap-custom-admin-group.css';
|
||||
import controller from './ldap-custom-admin-group.controller';
|
||||
|
||||
export const ldapCustomAdminGroup = {
|
||||
|
@ -9,5 +10,6 @@ export const ldapCustomAdminGroup = {
|
|||
defaultAdminGroupSearchFilter: '<',
|
||||
onSearchClick: '<',
|
||||
limitedFeatureId: '<',
|
||||
isLimitedFeatureSelfContained: '<',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
.ldap-custom-admin-group-title {
|
||||
float: initial;
|
||||
margin-top: 30px;
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
<div class="col-sm-12 form-section-title" style="float: initial;">
|
||||
Auto-populate team admins
|
||||
<div class="col-sm-12 form-section-title ldap-custom-admin-group-title" ng-style="$ctrl.isLimitedFeatureSelfContained && { 'padding-bottom': '15px' }">
|
||||
Auto-populate team admins <be-feature-indicator feature="$ctrl.limitedFeatureId" class="space-left" ng-if="$ctrl.isLimitedFeatureSelfContained"></be-feature-indicator>
|
||||
</div>
|
||||
|
||||
<rd-widget ng-repeat="config in $ctrl.settings.AdminGroupSearchSettings | limitTo: (1 - $ctrl.settings.AdminGroupSearchSettings)" style="display: block; margin-bottom: 10px;">
|
||||
<rd-widget ng-repeat="config in $ctrl.settings.AdminGroupSearchSettings | limitTo: (1 - $ctrl.settings.AdminGroupSearchSettings)">
|
||||
<rd-widget-body>
|
||||
<div class="form-group" ng-if="$index > 0" style="margin-bottom: 10px;">
|
||||
<div class="form-group m-b-10" ng-if="$index > 0">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
Extra search configuration
|
||||
</span>
|
||||
|
@ -16,7 +16,17 @@
|
|||
<portainer-tooltip position="bottom" message="The distinguished name of the element from which the LDAP server will search for groups."></portainer-tooltip>
|
||||
</label>
|
||||
<div class="col-sm-8 col-md-4">
|
||||
<input type="text" class="form-control" id="ldap_admin_group_basedn_{{ $index }}" ng-model="config.GroupBaseDN" placeholder="dc=ldap,dc=domain,dc=tld" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="ldap_admin_group_basedn_{{ $index }}"
|
||||
ng-model="config.GroupBaseDN"
|
||||
placeholder="dc=ldap,dc=domain,dc=tld"
|
||||
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
ng-disabled="{{ $ctrl.isLimitedFeatureSelfContained }}"
|
||||
limited-feature-tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label for="ldap_admin_group_att_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
|
||||
|
@ -24,7 +34,17 @@
|
|||
<portainer-tooltip position="bottom" message="LDAP attribute which denotes the group membership."></portainer-tooltip>
|
||||
</label>
|
||||
<div class="col-sm-8 col-md-4">
|
||||
<input type="text" class="form-control" id="ldap_admin_group_att_{{ $index }}" ng-model="config.GroupAttribute" placeholder="member" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="ldap_admin_group_att_{{ $index }}"
|
||||
ng-model="config.GroupAttribute"
|
||||
placeholder="member"
|
||||
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
ng-disabled="{{ $ctrl.isLimitedFeatureSelfContained }}"
|
||||
limited-feature-tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -33,7 +53,17 @@
|
|||
<portainer-tooltip position="bottom" message="The LDAP search filter used to select group elements, optional."></portainer-tooltip>
|
||||
</label>
|
||||
<div ng-class="{ 'col-sm-7 col-md-9': $index, 'col-sm-8 col-md-10': !$index }">
|
||||
<input type="text" class="form-control" id="ldap_admin_group_filter_{{ $index }}" ng-model="config.GroupFilter" placeholder="(objectClass=groupOfNames)" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="ldap_admin_group_filter_{{ $index }}"
|
||||
ng-model="config.GroupFilter"
|
||||
placeholder="(objectClass=groupOfNames)"
|
||||
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
ng-disabled="{{ $ctrl.isLimitedFeatureSelfContained }}"
|
||||
limited-feature-tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-sm-1" ng-if="$index > 0">
|
||||
<button class="btn btn-sm btn-danger" type="button" ng-click="$ctrl.onRemoveClick($index)">
|
||||
|
@ -44,20 +74,31 @@
|
|||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
|
||||
<div class="form-group" style="margin-top: 10px;">
|
||||
<div class="form-group m-t-10">
|
||||
<div class="col-sm-12">
|
||||
<button class="label label-default interactive" style="border: 0;" ng-click="$ctrl.onAddClick()">
|
||||
<button
|
||||
class="label label-default interactive no-border"
|
||||
ng-click="$ctrl.onAddClick()"
|
||||
limited-feature-dir="{{ $ctrl.limitedFeatureId }}"
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
limited-feature-disabled
|
||||
>
|
||||
<i class="fa fa-plus-circle" aria-hidden="true"></i> add group search configuration
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-12" style="margin-top: 10px;">
|
||||
<button class="btn btm-sm btn-primary" type="button" ng-click="$ctrl.search()" limited-feature-dir="{{ $ctrl.limitedFeatureId }}" limited-feature-tabindex="-1">
|
||||
<div class="col-sm-12 m-t-10">
|
||||
<button
|
||||
class="btn btm-sm btn-primary"
|
||||
type="button"
|
||||
ng-click="$ctrl.search()"
|
||||
limited-feature-dir="{{ $ctrl.limitedFeatureId }}"
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
ng-disabled="{{ $ctrl.isLimitedFeatureSelfContained }}"
|
||||
limited-feature-tabindex="-1"
|
||||
>
|
||||
Fetch Admin Group(s)
|
||||
</button>
|
||||
<be-feature-indicator feature="$ctrl.limitedFeatureId" class="space-left"></be-feature-indicator>
|
||||
<span ng-if="$ctrl.groups && $ctrl.groups.length === 0" style="margin-left: 30px;">
|
||||
<i class="fa fa-exclamation-triangle text-warning" aria-hidden="true"></i> No groups found</span
|
||||
>
|
||||
<span ng-if="$ctrl.groups && $ctrl.groups.length === 0" class="m-l-30"> <i class="fa fa-exclamation-triangle text-warning" aria-hidden="true"></i> No groups found</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -66,7 +107,7 @@
|
|||
<label for="admin-auto-populate" class="control-label text-left text-muted" ng-class="{ 'text-muted': !$ctrl.enableAssignAdminGroup }">
|
||||
Assign admin rights to group(s)
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<label class="switch m-l-20" ng-class="{ 'business limited': $ctrl.isLimitedFeatureSelfContained }">
|
||||
<input id="admin-auto-populate" ng-disabled="!$ctrl.enableAssignAdminGroup" name="admin-auto-populate" type="checkbox" ng-model="$ctrl.settings.AdminAutoPopulate" /><i></i>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -78,6 +119,7 @@
|
|||
Select Group(s)
|
||||
</label>
|
||||
<span
|
||||
class="m-l-20"
|
||||
isteven-multi-select
|
||||
ng-if="$ctrl.enableAssignAdminGroup"
|
||||
input-model="$ctrl.groups"
|
||||
|
@ -88,7 +130,6 @@
|
|||
helper-elements="filter"
|
||||
search-property="name"
|
||||
translation="{nothingSelected: 'Select one or more groups', search: 'Search...'}"
|
||||
style="margin-left: 20px;"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import './ldap-settings-custom.css';
|
||||
import controller from './ldap-settings-custom.controller';
|
||||
|
||||
export const ldapSettingsCustom = {
|
||||
|
@ -11,5 +12,8 @@ export const ldapSettingsCustom = {
|
|||
connectivityCheck: '<',
|
||||
onSearchUsersClick: '<',
|
||||
onSearchGroupsClick: '<',
|
||||
onSaveSettings: '<',
|
||||
saveButtonState: '<',
|
||||
saveButtonDisabled: '<',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { EXTERNAL_AUTH_LDAP } from '@/portainer/feature-flags/feature-ids';
|
||||
|
||||
export default class LdapSettingsCustomController {
|
||||
constructor() {
|
||||
this.limitedFeatureId = EXTERNAL_AUTH_LDAP;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
label[for='anonymous_mode'].control-label {
|
||||
padding-top: 0;
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
<div class="form-group">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<p>
|
||||
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
<i class="fa fa-info-circle blue-icon m-r-2" aria-hidden="true"></i>
|
||||
You can configure multiple LDAP Servers for authentication fallback. Make sure all servers are using the same configuration (i.e. if TLS is enabled, they should all use the
|
||||
same certificates).
|
||||
</p>
|
||||
|
@ -22,12 +22,11 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ldap_url" class="col-sm-3 col-lg-2 control-label text-left" style="display: flex; flex-wrap: wrap;">
|
||||
<label for="ldap_url" class="col-sm-3 col-lg-2 control-label text-left dispay-flex flex-wrap">
|
||||
LDAP Server
|
||||
<button
|
||||
type="button"
|
||||
class="label label-default interactive"
|
||||
style="border: 0;"
|
||||
class="label label-default interactive no-border"
|
||||
ng-click="$ctrl.addLDAPUrl()"
|
||||
limited-feature-dir="{{ $ctrl.limitedFeatureId }}"
|
||||
limited-feature-disabled
|
||||
|
@ -37,7 +36,7 @@
|
|||
</button>
|
||||
</label>
|
||||
<div class="col-sm-9 col-lg-10">
|
||||
<div ng-repeat="url in $ctrl.settings.URLs track by $index" style="display: flex; margin-bottom: 10px;">
|
||||
<div class="m-b-10 dispay-flex" ng-repeat="url in $ctrl.settings.URLs track by $index">
|
||||
<input type="text" class="form-control" id="ldap_url" ng-model="$ctrl.settings.URLs[$index]" placeholder="e.g. 10.0.0.10:389 or myldap.domain.tld:389" required />
|
||||
<button ng-if="$index > 0" class="btn btn-sm btn-danger" type="button" ng-click="$ctrl.removeLDAPUrl($index)">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
|
@ -46,14 +45,15 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Anonymous mode-->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label for="anonymous_mode" class="control-label text-left">
|
||||
Anonymous mode
|
||||
<portainer-tooltip position="bottom" message="Enable this option if the server is configured for Anonymous access."></portainer-tooltip>
|
||||
<label for="anonymous_mode" class="control-label text-left col-sm-3 col-lg-2">
|
||||
Anonymous mode
|
||||
<portainer-tooltip position="bottom" message="Enable this option if the server is configured for Anonymous access."></portainer-tooltip>
|
||||
</label>
|
||||
<div class="col-sm-9 col-lg-10">
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="anonymous_mode" ng-model="$ctrl.settings.AnonymousMode" limited-feature-dir="{{::$ctrl.limitedFeatureId}}" limited-feature-tabindex="-1" /><i></i>
|
||||
</label>
|
||||
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" id="anonymous_mode" ng-model="$ctrl.settings.AnonymousMode" /><i></i> </label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !Anonymous mode-->
|
||||
|
@ -102,29 +102,38 @@
|
|||
></ldap-connectivity-check>
|
||||
|
||||
<ldap-custom-user-search
|
||||
style="margin-top: 5px;"
|
||||
class="m-r-5"
|
||||
settings="$ctrl.settings.SearchSettings"
|
||||
on-search-click="($ctrl.onSearchUsersClick)"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
></ldap-custom-user-search>
|
||||
<ldap-custom-group-search
|
||||
style="margin-top: 5px;"
|
||||
class="m-r-5"
|
||||
settings="$ctrl.settings.GroupSearchSettings"
|
||||
on-search-click="($ctrl.onSearchGroupsClick)"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
></ldap-custom-group-search>
|
||||
|
||||
<div limited-feature-dir="{{ $ctrl.limitedFeatureId }}" limited-feature-class="limited-be" style="margin-bottom: 20px;">
|
||||
<ldap-custom-admin-group
|
||||
style="margin-top: 5px;"
|
||||
settings="$ctrl.settings"
|
||||
on-search-click="($ctrl.onSearchAdminGroupsClick)"
|
||||
selected-admin-groups="$ctrl.selectedAdminGroups"
|
||||
default-admin-group-search-filter="'(objectClass=groupOfNames)'"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
></ldap-custom-admin-group>
|
||||
</div>
|
||||
<ldap-custom-admin-group
|
||||
class="m-r-5"
|
||||
settings="$ctrl.settings"
|
||||
on-search-click="($ctrl.onSearchAdminGroupsClick)"
|
||||
selected-admin-groups="$ctrl.selectedAdminGroups"
|
||||
default-admin-group-search-filter="'(objectClass=groupOfNames)'"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
is-limited-feature-self-contained="true"
|
||||
></ldap-custom-admin-group>
|
||||
|
||||
<div limited-feature-dir="{{ $ctrl.limitedFeatureId }}" limited-feature-class="limited-be">
|
||||
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId" show-be-indicator-if-needed="true"></ldap-settings-test-login>
|
||||
</div>
|
||||
<ldap-settings-test-login
|
||||
settings="$ctrl.settings"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
show-be-indicator-if-needed="true"
|
||||
is-limited-feature-self-contained="true"
|
||||
></ldap-settings-test-login>
|
||||
|
||||
<save-auth-settings-button
|
||||
on-save-settings="($ctrl.onSaveSettings)"
|
||||
save-button-state="($ctrl.saveButtonState)"
|
||||
save-button-disabled="!$ctrl.saveButtonDisabled()"
|
||||
limited-feature-dir="{{ $ctrl.limitedFeatureId }}"
|
||||
></save-auth-settings-button>
|
||||
|
|
|
@ -8,9 +8,11 @@ export const ldapSettingsOpenLdap = {
|
|||
tlscaCert: '=',
|
||||
state: '=',
|
||||
connectivityCheck: '<',
|
||||
|
||||
onTlscaCertChange: '<',
|
||||
onSearchUsersClick: '<',
|
||||
onSearchGroupsClick: '<',
|
||||
onSaveSettings: '<',
|
||||
saveButtonState: '<',
|
||||
saveButtonDisabled: '<',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -184,4 +184,10 @@
|
|||
></ldap-group-search>
|
||||
|
||||
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId"></ldap-settings-test-login>
|
||||
<save-auth-settings-button
|
||||
on-save-settings="($ctrl.onSaveSettings)"
|
||||
save-button-state="($ctrl.saveButtonState)"
|
||||
save-button-disabled="!$ctrl.saveButtonDisabled()"
|
||||
limited-feature-id="$ctrl.limitedFeatureId"
|
||||
></save-auth-settings-button>
|
||||
</ng-form>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import './ldap-settings-test-login.css';
|
||||
import controller from './ldap-settings-test-login.controller';
|
||||
|
||||
export const ldapSettingsTestLogin = {
|
||||
|
@ -7,5 +8,6 @@ export const ldapSettingsTestLogin = {
|
|||
settings: '=',
|
||||
limitedFeatureId: '<',
|
||||
showBeIndicatorIfNeeded: '<',
|
||||
isLimitedFeatureSelfContained: '<',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
label[for='ldap_test_password'] {
|
||||
font-size: 0.9em;
|
||||
margin-right: 5px;
|
||||
}
|
|
@ -1,16 +1,31 @@
|
|||
<div class="col-sm-12 form-section-title">
|
||||
<div class="col-sm-12 form-section-title" ng-style="$ctrl.isLimitedFeatureSelfContained && { 'padding-bottom': '15px' }">
|
||||
Test login
|
||||
<be-feature-indicator
|
||||
ng-if="$ctrl.showBeIndicatorIfNeeded"
|
||||
feature="$ctrl.limitedFeatureId"
|
||||
class="space-left"
|
||||
ng-if="$ctrl.isLimitedFeatureSelfContained"
|
||||
></be-feature-indicator>
|
||||
</div>
|
||||
<div class="form-inline">
|
||||
<div class="form-group" style="margin: 0;">
|
||||
<label for="ldap_test_username" style="font-size: 0.9em; margin-right: 5px;">
|
||||
Username
|
||||
</label>
|
||||
<input type="text" class="form-control" id="ldap_test_username" ng-model="$ctrl.username" limited-feature-dir="{{::$ctrl.limitedFeatureId}}" limited-feature-tabindex="-1" />
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="ldap_test_username"
|
||||
ng-model="$ctrl.username"
|
||||
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
ng-disabled="{{ $ctrl.isLimitedFeatureSelfContained }}"
|
||||
limited-feature-tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="margin: 0;">
|
||||
<label for="ldap_test_password" style="font-size: 0.9em; margin-right: 5px;">
|
||||
<div class="form-group no-margin">
|
||||
<label for="ldap_test_password">
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
|
@ -20,18 +35,20 @@
|
|||
ng-model="$ctrl.password"
|
||||
autocomplete="new-password"
|
||||
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
ng-disabled="{{ $ctrl.isLimitedFeatureSelfContained }}"
|
||||
limited-feature-tabindex="-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="margin: 0;">
|
||||
<div class="form-group no-margin">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
ng-disabled="$ctrl.state.testStatus === $ctrl.TEST_STATUS.LOADING || !$ctrl.username || !$ctrl.password"
|
||||
ng-click="$ctrl.testLogin($ctrl.username, $ctrl.password)"
|
||||
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
|
||||
limited-feature-disabled
|
||||
limited-feature-class=" {{ $ctrl.isLimitedFeatureSelfContained && 'limited-be' }}"
|
||||
limited-feature-tabindex="-1"
|
||||
>
|
||||
<span ng-if="$ctrl.state.testStatus !== $ctrl.TEST_STATUS.LOADING">Test</span>
|
||||
|
@ -40,6 +57,4 @@
|
|||
<i ng-if="$ctrl.state.testStatus === $ctrl.TEST_STATUS.SUCCESS" class="fa fa-check green-icon"></i>
|
||||
<i ng-if="$ctrl.state.testStatus === $ctrl.TEST_STATUS.FAILURE" class="fa fa-times red-icon"></i>
|
||||
</div>
|
||||
|
||||
<be-feature-indicator ng-if="$ctrl.showBeIndicatorIfNeeded" feature="$ctrl.limitedFeatureId" class="space-left"></be-feature-indicator>
|
||||
</div>
|
||||
|
|
|
@ -7,5 +7,8 @@ export const ldapSettings = {
|
|||
settings: '=',
|
||||
state: '<',
|
||||
connectivityCheck: '<',
|
||||
onSaveSettings: '<',
|
||||
saveButtonState: '<',
|
||||
isLdapFormValid: '<',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
connectivity-check="$ctrl.connectivityCheck"
|
||||
on-search-users-click="($ctrl.searchUsers)"
|
||||
on-search-groups-click="($ctrl.searchGroups)"
|
||||
on-save-settings="($ctrl.onSaveSettings)"
|
||||
save-button-state="($ctrl.saveButtonState)"
|
||||
save-button-disabled="$ctrl.isLdapFormValid"
|
||||
></ldap-settings-custom>
|
||||
<ldap-settings-open-ldap
|
||||
ng-if="$ctrl.settings.ServerType === $ctrl.SERVER_TYPES.OPEN_LDAP"
|
||||
|
@ -37,5 +40,8 @@
|
|||
connectivity-check="$ctrl.connectivityCheck"
|
||||
on-search-users-click="($ctrl.searchUsers)"
|
||||
on-search-groups-click="($ctrl.searchGroups)"
|
||||
on-save-settings="($ctrl.onSaveSettings)"
|
||||
save-button-state="($ctrl.saveButtonState)"
|
||||
save-button-disabled="$ctrl.isLdapFormValid"
|
||||
></ldap-settings-open-ldap>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
export const saveAuthSettingsButton = {
|
||||
templateUrl: './save-auth-settings-button.html',
|
||||
bindings: {
|
||||
onSaveSettings: '<',
|
||||
saveButtonDisabled: '<',
|
||||
saveButtonState: '<',
|
||||
limitedFeatureId: '<',
|
||||
limitedFeatureClass: '<',
|
||||
className: '<',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,19 @@
|
|||
<div class="col-sm-12 form-section-title">
|
||||
Actions
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button
|
||||
type="button"
|
||||
ng-class="[$ctrl.className, 'btn btn-primary btn-sm']"
|
||||
ng-click="$ctrl.onSaveSettings()"
|
||||
ng-disabled="$ctrl.saveButtonDisabled || $ctrl.saveButtonState"
|
||||
button-spinner="$ctrl.saveButtonState"
|
||||
limited-feature-dir="{{::$ctrl.limitedFeatureId}}"
|
||||
limited-feature-class="{{::$ctrl.limitedFeatureClass}}"
|
||||
>
|
||||
<span ng-hide="$ctrl.saveButtonState">Save settings</span>
|
||||
<span ng-show="$ctrl.saveButtonState">Saving...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
|
@ -25,7 +25,9 @@
|
|||
</p>
|
||||
|
||||
<div>
|
||||
<button type="button" class="btn btn-sm btn-primary" style="margin-right: 10px;"> <i class="fa fa-download space-right" aria-hidden="true"></i>Export as CSV </button>
|
||||
<button type="button" class="btn btn-sm btn-primary m-r-10" limited-feature-dir="{{::$ctrl.limitedFeature}}" limited-feature-class="limited-be" limited-feature-disabled>
|
||||
<i class="fa fa-download space-right" aria-hidden="true"></i>Export as CSV
|
||||
</button>
|
||||
<be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator>
|
||||
</div>
|
||||
</rd-widget-body>
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
</p>
|
||||
|
||||
<div>
|
||||
<button type="button" class="btn btn-sm btn-primary" style="margin-right: 10px;"><i class="fa fa-download space-right" aria-hidden="true"></i>Export as CSV </button>
|
||||
<button type="button" class="btn btn-sm btn-primary m-r-10" limited-feature-dir="{{::$ctrl.limitedFeature}}" limited-feature-class="limited-be" limited-feature-disabled
|
||||
><i class="fa fa-download space-right" aria-hidden="true"></i>Export as CSV
|
||||
</button>
|
||||
<be-feature-indicator feature="$ctrl.limitedFeature"></be-feature-indicator>
|
||||
</div>
|
||||
</rd-widget-body>
|
||||
|
|
|
@ -37,14 +37,7 @@
|
|||
|
||||
<box-selector radio-name="authOptions" ng-model="authMethod" options="authOptions" on-change="(onChangeAuthMethod)"></box-selector>
|
||||
|
||||
<div ng-if="authenticationMethodSelected(1)">
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Information
|
||||
</div>
|
||||
<div class="form-group col-sm-12 text-muted small">
|
||||
When using internal authentication, Portainer will encrypt user passwords and store credentials locally.
|
||||
</div>
|
||||
</div>
|
||||
<internal-auth ng-if="authenticationMethodSelected(1)" on-save-settings="(saveSettings)" save-button-state="state.actionInProgress"></internal-auth>
|
||||
|
||||
<ldap-settings
|
||||
ng-if="authenticationMethodSelected(2)"
|
||||
|
@ -52,6 +45,9 @@
|
|||
tlsca-cert="formValues.TLSCACert"
|
||||
state="state"
|
||||
connectivity-check="LDAPConnectivityCheck"
|
||||
on-save-settings="(saveSettings)"
|
||||
save-button-state="state.actionInProgress"
|
||||
is-ldap-form-valid="isLDAPFormValid"
|
||||
></ldap-settings>
|
||||
|
||||
<ad-settings
|
||||
|
@ -60,29 +56,18 @@
|
|||
tlsca-cert="formValues.TLSCACert"
|
||||
state="state"
|
||||
connectivity-check="LDAPConnectivityCheck"
|
||||
on-save-settings="(saveSettings)"
|
||||
save-button-state="state.actionInProgress"
|
||||
is-ldap-form-valid="isLDAPFormValid()"
|
||||
></ad-settings>
|
||||
|
||||
<oauth-settings ng-if="authenticationMethodSelected(3)" settings="OAuthSettings" teams="teams"></oauth-settings>
|
||||
|
||||
<!-- actions -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Actions
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
ng-click="saveSettings()"
|
||||
ng-disabled="state.actionInProgress || (settings.AuthenticationMethod === 2 && !isLDAPFormValid()) || (settings.AuthenticationMethod === 3 && !isOAuthTeamMembershipFormValid()) || authSettingsForm.$invalid"
|
||||
button-spinner="state.actionInProgress"
|
||||
>
|
||||
<span ng-hide="state.actionInProgress">Save settings</span>
|
||||
<span ng-show="state.actionInProgress">Saving...</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !actions -->
|
||||
<oauth-settings
|
||||
ng-if="authenticationMethodSelected(3)"
|
||||
settings="OAuthSettings"
|
||||
teams="teams"
|
||||
on-save-settings="(saveSettings)"
|
||||
save-button-state="state.actionInProgress"
|
||||
></oauth-settings>
|
||||
</form>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
|
|
|
@ -182,7 +182,8 @@ function SettingsAuthenticationController($q, $scope, $state, Notifications, Set
|
|||
return (
|
||||
_.compact(ldapSettings.URLs).length &&
|
||||
(ldapSettings.AnonymousMode || (ldapSettings.ReaderDN && ldapSettings.Password)) &&
|
||||
(!isTLSMode || $scope.formValues.TLSCACert || ldapSettings.TLSConfig.TLSSkipVerify)
|
||||
(!isTLSMode || $scope.formValues.TLSCACert || ldapSettings.TLSConfig.TLSSkipVerify) &&
|
||||
(!$scope.settings.LDAPSettings.AdminAutoPopulate || ($scope.settings.LDAPSettings.AdminAutoPopulate && $scope.formValues.selectedAdminGroups.length > 0))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue