From aa5cbdbb32981c64d5a6fc514d17460ddb6a4b29 Mon Sep 17 00:00:00 2001 From: Lukas Wagner Date: Fri, 17 Mar 2023 09:47:18 +0100 Subject: [PATCH] auth ui: add LDAP realm edit panel The panel was mostly taken from from PVE, but altered slightly: - bind-dn and bind-password are displayed under "General" and not under "Sync". For some servers, we need to be bound to lookup a user's domain from a given user id attribute. In PVE, the bind-dn and bind-password fields are under "Sync", which is a bit confusing if a user is not interested in automatic user syncing. - There is a 'anonymous search' checkbox. The value is not persisted in the configuration, it merely enables/disables the bind-dn and bind-password fiels to make their intent a bit more clear. - Instead of a 'secure' checkbox, a combobox for TLS mode is shown. This way users can select between LDAP, STARTLS and LDAPS. In PVE, the 'secure' config parameter is deprecated anyway, so I took the opportunity to replace it with the 'mode' parameter as described. - Parameters now consistently use kebab-case for naming. If PVE is modified to use the same panel, some sort of adapter will be needed. Signed-off-by: Lukas Wagner --- src/Makefile | 1 + src/Schema.js | 8 ++ src/window/AuthEditLDAP.js | 194 +++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 src/window/AuthEditLDAP.js diff --git a/src/Makefile b/src/Makefile index 11790a0..f65f91a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -84,6 +84,7 @@ JSSRC= \ window/FileBrowser.js \ window/AuthEditBase.js \ window/AuthEditOpenId.js \ + window/AuthEditLDAP.js \ window/TfaWindow.js \ window/AddTfaRecovery.js \ window/AddTotp.js \ diff --git a/src/Schema.js b/src/Schema.js index d414845..372af89 100644 --- a/src/Schema.js +++ b/src/Schema.js @@ -17,6 +17,14 @@ Ext.define('Proxmox.Schema', { // a singleton pwchange: false, iconCls: 'pmx-itype-icon-openid-logo', }, + ldap: { + name: gettext('LDAP Server'), + ipanel: 'pmxAuthLDAPPanel', + add: true, + edit: true, + tfa: true, + pwchange: false, + }, }, // to add or change existing for product specific ones overrideAuthDomains: function(extra) { diff --git a/src/window/AuthEditLDAP.js b/src/window/AuthEditLDAP.js new file mode 100644 index 0000000..a44c536 --- /dev/null +++ b/src/window/AuthEditLDAP.js @@ -0,0 +1,194 @@ + +Ext.define('Proxmox.panel.LDAPInputPanelViewModel', { + extend: 'Ext.app.ViewModel', + + alias: 'viewmodel.pmxAuthLDAPPanel', + + data: { + mode: 'ldap', + anonymous_search: 1, + }, + + formulas: { + tls_enabled: function(get) { + return get('mode') !== 'ldap'; + }, + }, + +}); + + +Ext.define('Proxmox.panel.LDAPInputPanel', { + extend: 'Proxmox.panel.InputPanel', + xtype: 'pmxAuthLDAPPanel', + mixins: ['Proxmox.Mixin.CBind'], + + viewModel: { + type: 'pmxAuthLDAPPanel', + }, + + type: 'ldap', + + onGetValues: function(values) { + if (this.isCreate) { + values.type = this.type; + } + + if (values.anonymous_search) { + if (!values.delete) { + values.delete = []; + } + + if (!Array.isArray(values.delete)) { + let tmp = values.delete; + values.delete = []; + values.delete.push(tmp); + } + + values.delete.push("bind-dn"); + values.delete.push("password"); + } + + delete values.anonymous_search; + + return values; + }, + + onSetValues: function(values) { + values.anonymous_search = values["bind-dn"] ? 0 : 1; + + return values; + }, + + + column1: [ + { + xtype: 'pmxDisplayEditField', + name: 'realm', + cbind: { + value: '{realm}', + editable: '{isCreate}', + }, + fieldLabel: gettext('Realm'), + allowBlank: false, + }, + { + xtype: 'proxmoxtextfield', + fieldLabel: gettext('Base Domain Name'), + name: 'base-dn', + allowBlank: false, + emptyText: 'cn=Users,dc=company,dc=net', + }, + { + xtype: 'proxmoxtextfield', + fieldLabel: gettext('User Attribute Name'), + name: 'user-attr', + allowBlank: false, + emptyText: 'uid / sAMAccountName', + }, + { + xtype: 'proxmoxcheckbox', + fieldLabel: gettext('Anonymous Search'), + name: 'anonymous_search', + bind: '{anonymous_search}', + }, + { + xtype: 'proxmoxtextfield', + fieldLabel: gettext('Bind Domain Name'), + name: 'bind-dn', + allowBlank: false, + emptyText: 'cn=user,dc=company,dc=net', + bind: { + disabled: "{anonymous_search}", + }, + }, + { + xtype: 'proxmoxtextfield', + inputType: 'password', + fieldLabel: gettext('Bind Password'), + name: 'password', + allowBlank: true, + cbind: { + emptyText: get => !get('isCreate') ? gettext('Unchanged') : '', + }, + bind: { + disabled: "{anonymous_search}", + }, + }, + ], + + column2: [ + { + xtype: 'proxmoxtextfield', + name: 'server1', + fieldLabel: gettext('Server'), + allowBlank: false, + }, + { + xtype: 'proxmoxtextfield', + name: 'server2', + fieldLabel: gettext('Fallback Server'), + submitEmpty: false, + cbind: { + deleteEmpty: '{!isCreate}', + }, + }, + { + xtype: 'proxmoxintegerfield', + name: 'port', + fieldLabel: gettext('Port'), + minValue: 1, + maxValue: 65535, + emptyText: gettext('Default'), + submitEmptyText: false, + deleteEmpty: true, + }, + { + xtype: 'proxmoxKVComboBox', + name: 'mode', + fieldLabel: gettext('Mode'), + editable: false, + comboItems: [ + ['ldap', 'LDAP'], + ['ldap+starttls', 'STARTTLS'], + ['ldaps', 'LDAPS'], + ], + bind: "{mode}", + cbind: { + deleteEmpty: '{!isCreate}', + value: get => get('isCreate') ? 'ldap' : 'LDAP', + }, + }, + { + xtype: 'proxmoxcheckbox', + fieldLabel: gettext('Verify Certificate'), + name: 'verify', + value: 0, + cbind: { + deleteEmpty: '{!isCreate}', + }, + + bind: { + disabled: '{!tls_enabled}', + }, + autoEl: { + tag: 'div', + 'data-qtip': gettext('Verify TLS certificate of the server'), + }, + + }, + ], + + columnB: [ + { + xtype: 'textfield', + name: 'comment', + fieldLabel: gettext('Comment'), + cbind: { + deleteEmpty: '{!isCreate}', + }, + }, + ], + +}); +