From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <l.wagner@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id 665CB91BB9
 for <pbs-devel@lists.proxmox.com>; Thu,  9 Feb 2023 14:32:05 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id 623CA249A4
 for <pbs-devel@lists.proxmox.com>; Thu,  9 Feb 2023 14:31:41 +0100 (CET)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS
 for <pbs-devel@lists.proxmox.com>; Thu,  9 Feb 2023 14:31:37 +0100 (CET)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 5E40B4654D
 for <pbs-devel@lists.proxmox.com>; Thu,  9 Feb 2023 14:31:37 +0100 (CET)
From: Lukas Wagner <l.wagner@proxmox.com>
To: pbs-devel@lists.proxmox.com
Date: Thu,  9 Feb 2023 14:31:25 +0100
Message-Id: <20230209133128.695211-16-l.wagner@proxmox.com>
X-Mailer: git-send-email 2.30.2
In-Reply-To: <20230209133128.695211-1-l.wagner@proxmox.com>
References: <20230209133128.695211-1-l.wagner@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL -0.192 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pbs-devel] [PATCH v3 proxmox-widget-toolkit 15/18] auth ui: add
 LDAP realm edit panel
X-BeenThere: pbs-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox Backup Server development discussion
 <pbs-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pbs-devel/>
List-Post: <mailto:pbs-devel@lists.proxmox.com>
List-Help: <mailto:pbs-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Thu, 09 Feb 2023 13:32:05 -0000

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 <l.wagner@proxmox.com>
---
 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 95da5aa..a24ae43 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -83,6 +83,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}',
+	    },
+	},
+    ],
+
+});
+
-- 
2.30.2