add ACME account panel

Copied from PVE with URLs now being based on the 'acmeUrl'
property which should point to the acme/ root containing
/tos, /directories, etc.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-03-16 11:24:21 +01:00 committed by Thomas Lamprecht
parent 60fead29a8
commit 5df894de26
3 changed files with 322 additions and 0 deletions

View File

@ -50,6 +50,7 @@ JSSRC= \
panel/RRDChart.js \
panel/GaugeWidget.js \
panel/Certificates.js \
panel/ACMEAccount.js \
window/Edit.js \
window/PasswordEdit.js \
window/SafeDestroy.js \
@ -58,6 +59,7 @@ JSSRC= \
window/DiskSmart.js \
window/ZFSDetail.js \
window/Certificates.js \
window/ACMEAccount.js \
node/APT.js \
node/NetworkEdit.js \
node/NetworkView.js \

116
src/panel/ACMEAccount.js Normal file
View File

@ -0,0 +1,116 @@
Ext.define('Proxmox.panel.ACMEAccounts', {
extend: 'Ext.grid.Panel',
xtype: 'pmxACMEAccounts',
title: gettext('Accounts'),
acmeUrl: undefined,
controller: {
xclass: 'Ext.app.ViewController',
addAccount: function() {
let me = this;
let view = me.getView();
let defaultExists = view.getStore().findExact('name', 'default') !== -1;
Ext.create('Proxmox.window.ACMEAccountCreate', {
defaultExists,
acmeUrl: view.acmeUrl,
taskDone: function() {
me.reload();
},
}).show();
},
viewAccount: function() {
let me = this;
let view = me.getView();
let selection = view.getSelection();
if (selection.length < 1) return;
Ext.create('Proxmox.window.ACMEAccountView', {
url: `${view.acmeUrl}/account/${selection[0].data.name}`,
}).show();
},
reload: function() {
let me = this;
let view = me.getView();
view.getStore().rstore.load();
},
showTaskAndReload: function(options, success, response) {
let me = this;
if (!success) return;
let upid = response.result.data;
Ext.create('Proxmox.window.TaskProgress', {
upid,
taskDone: function() {
me.reload();
},
}).show();
},
},
minHeight: 150,
emptyText: gettext('No Accounts configured'),
columns: [
{
dataIndex: 'name',
text: gettext('Name'),
renderer: Ext.String.htmlEncode,
flex: 1,
},
],
listeners: {
itemdblclick: 'viewAccount',
},
store: {
type: 'diff',
autoDestroy: true,
autoDestroyRstore: true,
rstore: {
type: 'update',
storeid: 'proxmox-acme-accounts',
model: 'proxmox-acme-accounts',
autoStart: true,
},
sorters: 'name',
},
initComponent: function() {
let me = this;
if (!me.acmeUrl) {
throw "no acmeUrl given";
}
Ext.apply(me, {
tbar: [
{
xtype: 'proxmoxButton',
text: gettext('Add'),
selModel: false,
handler: 'addAccount',
},
{
xtype: 'proxmoxButton',
text: gettext('View'),
handler: 'viewAccount',
disabled: true,
},
{
xtype: 'proxmoxStdRemoveButton',
baseurl: `${me.acmeUrl}/account`,
callback: 'showTaskAndReload',
},
],
});
me.callParent();
me.store.rstore.proxy.setUrl(`/api2/json/${me.acmeUrl}/account`);
},
});

204
src/window/ACMEAccount.js Normal file
View File

@ -0,0 +1,204 @@
Ext.define('Proxmox.window.ACMEAccountCreate', {
extend: 'Proxmox.window.Edit',
mixins: ['Proxmox.Mixin.CBind'],
xtype: 'pmxACMEAccountCreate',
acmeUrl: undefined,
width: 450,
title: gettext('Register Account'),
isCreate: true,
method: 'POST',
submitText: gettext('Register'),
showTaskViewer: true,
defaultExists: false,
items: [
{
xtype: 'proxmoxtextfield',
fieldLabel: gettext('Account Name'),
name: 'name',
cbind: {
emptyText: (get) => get('defaultExists') ? '' : 'default',
allowBlank: (get) => !get('defaultExists'),
},
},
{
xtype: 'textfield',
name: 'contact',
vtype: 'email',
allowBlank: false,
fieldLabel: gettext('E-Mail'),
},
{
xtype: 'proxmoxComboGrid',
name: 'directory',
reference: 'directory',
allowBlank: false,
valueField: 'url',
displayField: 'name',
fieldLabel: gettext('ACME Directory'),
store: {
autoLoad: true,
fields: ['name', 'url'],
idProperty: ['name'],
proxy: { type: 'proxmox' },
sorters: {
property: 'name',
order: 'ASC',
},
},
listConfig: {
columns: [
{
header: gettext('Name'),
dataIndex: 'name',
flex: 1,
},
{
header: gettext('URL'),
dataIndex: 'url',
flex: 1,
},
],
},
listeners: {
change: function(combogrid, value) {
let me = this;
if (!value) {
return;
}
let acmeUrl = me.up('window').acmeUrl;
let disp = me.up('window').down('#tos_url_display');
let field = me.up('window').down('#tos_url');
let checkbox = me.up('window').down('#tos_checkbox');
disp.setValue(gettext('Loading'));
field.setValue(undefined);
checkbox.setValue(undefined);
checkbox.setHidden(true);
Proxmox.Utils.API2Request({
url: `${acmeUrl}/tos`,
method: 'GET',
params: {
directory: value,
},
success: function(response, opt) {
field.setValue(response.result.data);
disp.setValue(response.result.data);
checkbox.setHidden(false);
},
failure: function(response, opt) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
});
},
},
},
{
xtype: 'displayfield',
itemId: 'tos_url_display',
renderer: Proxmox.Utils.render_optional_url,
name: 'tos_url_display',
},
{
xtype: 'hidden',
itemId: 'tos_url',
name: 'tos_url',
},
{
xtype: 'proxmoxcheckbox',
itemId: 'tos_checkbox',
boxLabel: gettext('Accept TOS'),
submitValue: false,
validateValue: function(value) {
if (value && this.checked) {
return true;
}
return false;
},
},
],
initComponent: function() {
let me = this;
if (!me.acmeUrl) {
throw "no acmeUrl given";
}
me.url = `${me.acmeUrl}/account`;
me.callParent();
me.lookup('directory')
.store
.proxy
.setUrl(`/api2/json/${me.acmeUrl}/directories`);
},
});
Ext.define('Proxmox.window.ACMEAccountView', {
extend: 'Proxmox.window.Edit',
xtype: 'pmxACMEAccountView',
width: 600,
fieldDefaults: {
labelWidth: 140,
},
title: gettext('Account'),
items: [
{
xtype: 'displayfield',
fieldLabel: gettext('E-Mail'),
name: 'email',
},
{
xtype: 'displayfield',
fieldLabel: gettext('Created'),
name: 'createdAt',
},
{
xtype: 'displayfield',
fieldLabel: gettext('Status'),
name: 'status',
},
{
xtype: 'displayfield',
fieldLabel: gettext('Directory'),
renderer: Proxmox.Utils.render_optional_url,
name: 'directory',
},
{
xtype: 'displayfield',
fieldLabel: gettext('Terms of Services'),
renderer: Proxmox.Utils.render_optional_url,
name: 'tos',
},
],
initComponent: function() {
var me = this;
me.callParent();
// hide OK/Reset button, because we just want to show data
me.down('toolbar[dock=bottom]').setVisible(false);
me.load({
success: function(response) {
var data = response.result.data;
data.email = data.account.contact[0];
data.createdAt = data.account.createdAt;
data.status = data.account.status;
me.setValues(data);
},
});
},
});