]> git.proxmox.com Git - pve-manager.git/commitdiff
ui: add Token Panel + Edit Window
authorFabian Grünbichler <f.gruenbichler@proxmox.com>
Tue, 21 Jan 2020 12:54:27 +0000 (13:54 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Sat, 25 Apr 2020 16:25:06 +0000 (18:25 +0200)
modeled after UserView and related code.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
www/manager6/Makefile
www/manager6/dc/Config.js
www/manager6/dc/TokenEdit.js [new file with mode: 0644]
www/manager6/dc/TokenView.js [new file with mode: 0644]
www/manager6/form/TokenSelector.js [new file with mode: 0644]

index 3aa2b87b5052225fc31e8a94be55e8a92e3ccb38..a70f4d7db1af59aed361ce33885ec2d1a2f03911 100644 (file)
@@ -241,6 +241,9 @@ JSSRC=                                                      \
        dc/Cluster.js                                   \
        dc/ClusterEdit.js                               \
        dc/PermissionView.js                            \
+       dc/TokenView.js                                 \
+       dc/TokenEdit.js                                 \
+       form/TokenSelector.js                           \
        Workspace.js
 
 lint: ${JSSRC}
index bed7a36c9d3ec9c958f6bb710b4820cd6b8015c0..ec099494612d649eafe3bf6235eff125ae7c2593 100644 (file)
@@ -87,6 +87,14 @@ Ext.define('PVE.dc.Config', {
            itemId: 'users'
        });
 
+       me.items.push({
+           xtype: 'pveTokenView',
+           groups: ['permissions'],
+           iconCls: 'fa fa-user-o',
+           title: gettext('API Tokens'),
+           itemId: 'apitokens'
+       });
+
        if (caps.dc['Sys.Audit']) {
            me.items.push({
                xtype: 'pveGroupView',
diff --git a/www/manager6/dc/TokenEdit.js b/www/manager6/dc/TokenEdit.js
new file mode 100644 (file)
index 0000000..c047c17
--- /dev/null
@@ -0,0 +1,125 @@
+Ext.define('PVE.dc.TokenEdit', {
+    extend: 'Proxmox.window.Edit',
+    alias: ['widget.pveDcTokenEdit'],
+
+    isAdd: true,
+
+    initComponent: function() {
+       var me = this;
+
+       me.isCreate = !me.tokenid;
+
+       var url;
+       var method;
+       var realm;
+
+       if (me.isCreate) {
+           url = '/invalid';
+           method = 'POST';
+       } else {
+           url = '/api2/extjs/access/users/' + encodeURIComponent(me.userid) + '/token/' + encodeURIComponent(me.tokenid);
+           method = 'PUT';
+       }
+
+       var column1 = [
+           {
+               xtype: me.isCreate ? 'pveUserSelector' : 'displayfield',
+               name: 'userid',
+               fieldLabel: gettext('User'),
+               value: me.userid,
+               allowBlank: false,
+               submitValue: me.isCreate ? true : false
+           },
+           {
+               xtype: me.isCreate ? 'textfield' : 'displayfield',
+               name: 'tokenid',
+               fieldLabel: gettext('Token ID'),
+               value: me.tokenid,
+               allowBlank: false,
+               submitValue: me.isCreate ? true : false
+           }
+       ];
+
+       var column2 = [
+           {
+               xtype: 'proxmoxcheckbox',
+               name: 'privsep',
+               checked: true,
+               uncheckedValue: 0,
+               fieldLabel: gettext('Privilege Separation')
+           },
+           {
+               xtype: 'datefield',
+               name: 'expire',
+               emptyText: 'never',
+               format: 'Y-m-d',
+               submitFormat: 'U',
+               fieldLabel: gettext('Expire')
+           }
+       ];
+
+       var ipanel = Ext.create('Proxmox.panel.InputPanel', {
+           column1: column1,
+           column2: column2,
+           columnB: [
+               {
+                   xtype: 'textfield',
+                   name: 'comment',
+                   fieldLabel: gettext('Comment')
+               }
+           ],
+           onGetValues: function(values) {
+               // hack: ExtJS datefield does not submit 0, so we need to set that
+               if (!values.expire) {
+                   values.expire = 0;
+               }
+
+               if (me.isCreate) {
+                   if (values.tokenid && values.userid) {
+                       me.url = '/api2/extjs/access/users/' + encodeURIComponent(values.userid) + '/token/' + encodeURIComponent(values.tokenid);
+                   } else {
+                       me.url = '/invalid';
+                   }
+                   delete values.userid;
+                   delete values.tokenid;
+               }
+
+               return values;
+           }
+       });
+
+       Ext.applyIf(me, {
+           subject: gettext('User'),
+           url: url,
+           method: method,
+           fieldDefaults: {
+               labelWidth: 110 // for spanish translation 
+           },
+           items: [ ipanel ]
+       });
+
+       me.callParent();
+
+       if (!me.isCreate) {
+           me.load({
+               success: function(response, options) {
+                   var data = response.result.data;
+                   if (Ext.isDefined(data.expire)) {
+                       if (data.expire) {
+                           data.expire = new Date(data.expire * 1000);
+                       } else {
+                           // display 'never' instead of '1970-01-01'
+                           data.expire = null;
+                       }
+                   }
+                   me.setValues(data);
+               }
+           });
+       }
+    },
+    apiCallDone: function(success, response, options) {
+       if (success && response.result.data.value) {
+           Ext.Msg.alert(gettext('API Token'), gettext('Please record the following API token value - it will only be displayed now') + ':<br/>' + response.result.data.value);
+       }
+    }
+});
diff --git a/www/manager6/dc/TokenView.js b/www/manager6/dc/TokenView.js
new file mode 100644 (file)
index 0000000..201aac5
--- /dev/null
@@ -0,0 +1,203 @@
+/*jslint confusion: true */
+Ext.define('PVE.dc.TokenView', {
+    extend: 'Ext.grid.GridPanel',
+
+    alias: ['widget.pveTokenView'],
+
+    onlineHelp: 'chapter_user_management',
+
+    stateful: true,
+    stateId: 'grid-tokens',
+
+    // use fixed user
+    userid: undefined,
+
+    initComponent : function() {
+       var me = this;
+
+       var caps = Ext.state.Manager.get('GuiCap');
+
+       var store = new Ext.data.Store({
+            id: "tokens",
+           model: 'pve-tokens',
+           sorters: [
+               {
+                   property: 'userid',
+                   order: 'ASC'
+               },
+               {
+                   property: 'tokenid',
+                   order: 'ASC',
+               }
+           ]
+       });
+
+       var reload = function() {
+           Proxmox.Utils.API2Request({
+               url: '/access/users/?full=1',
+               method: 'GET',
+               failure: function(response, opts) {
+                   Proxmox.Utils.setErrorMask(me, response.htmlStatus);
+                   me.load_task.delay(me.load_delay);
+               },
+               success: function(response, opts) {
+                   Proxmox.Utils.setErrorMask(me, false);
+                   var result = Ext.decode(response.responseText);
+                   var data = result.data || [];
+                   var records = [];
+                   Ext.Array.each(data, function(user) {
+                       tokens = user.tokens || [];
+                       Ext.Array.each(tokens, function(token) {
+                           var r = {};
+                           r.id = user.userid + '!' + token.tokenid;
+                           r.userid = user.userid;
+                           r.tokenid = token.tokenid;
+                           r.comment = token.comment;
+                           r.expire = token.expire;
+                           r.privsep = token.privsep === 1 ? true : false;
+                           records.push(r);
+                       });
+                   });
+                   store.loadData(records);
+               },
+           });
+       };
+
+       var sm = Ext.create('Ext.selection.RowModel', {});
+
+       var remove_btn = Ext.create('Proxmox.button.StdRemoveButton', {
+           selModel: sm,
+           enableFn: function(rec) {
+               return !!caps.access['User.Modify'];
+           },
+           callback: function() {
+               reload();
+           },
+           getUrl: function(rec) {
+               return '/access/users/' + encodeURIComponent(rec.data.userid) + '/token/' + encodeURIComponent(rec.data.tokenid);
+           }
+        });
+       var run_editor = function() {
+           var rec = sm.getSelection()[0];
+           if (!rec || !caps.access['User.Modify']) {
+               return;
+           }
+
+            var win = Ext.create('PVE.dc.TokenEdit', {
+               userid: rec.data.userid,
+               tokenid: rec.data.tokenid
+            });
+            win.on('destroy', reload);
+            win.show();
+       };
+
+       var edit_btn = new Proxmox.button.Button({
+           text: gettext('Edit'),
+           disabled: true,
+           enableFn: function(rec) {
+               return !!caps.access['User.Modify'];
+           },
+           selModel: sm,
+           handler: run_editor
+       });
+
+       var perm_btn = new Proxmox.button.Button({
+           text: gettext('Permissions'),
+           disabled: false,
+           selModel: sm,
+           handler: function(btn, event, rec) {
+               var rec = sm.getSelection()[0];
+               var win = Ext.create('PVE.dc.PermissionView', {
+                   userid: rec.data.id
+               });
+               win.show();
+           }
+       });
+
+        var tbar = [
+            {
+               text: gettext('Add'),
+               disabled: !caps.access['User.Modify'],
+               handler: function() {
+                   var rec = sm.getSelection()[0];
+                   var data = {};
+                   if (rec && rec.data) {
+                       data.userid = rec.data.userid;
+                   }
+                   var win = Ext.create('PVE.dc.TokenEdit', data);
+                   win.on('destroy', reload);
+                   win.show();
+               }
+            },
+           edit_btn, remove_btn, perm_btn
+        ];
+
+       var render_username = function(userid) {
+           return userid.match(/^(.+)(@[^@]+)$/)[1];
+       };
+
+       var render_realm = function(userid) {
+           return userid.match(/@([^@]+)$/)[1];
+       };
+
+
+       Ext.apply(me, {
+           store: store,
+           selModel: sm,
+           tbar: tbar,
+           viewConfig: {
+               trackOver: false
+           },
+           columns: [
+               {
+                   header: gettext('User name'),
+                   width: 200,
+                   sortable: true,
+                   renderer: render_username,
+                   dataIndex: 'userid'
+               },
+               {
+                   header: gettext('Realm'),
+                   width: 100,
+                   sortable: true,
+                   renderer: render_realm,
+                   dataIndex: 'userid'
+               },
+               {
+                   header: gettext('Token name'),
+                   width: 100,
+                   sortable: true,
+                   dataIndex: 'tokenid'
+               },
+               {
+                   header: gettext('Expire'),
+                   width: 80,
+                   sortable: true,
+                   renderer: Proxmox.Utils.format_expire,
+                   dataIndex: 'expire'
+               },
+               {
+                   header: gettext('Comment'),
+                   sortable: false,
+                   renderer: Ext.String.htmlEncode,
+                   dataIndex: 'comment',
+                   flex: 1
+               },
+               {
+                   header: gettext('Privilege Separation'),
+                   width: 80,
+                   sortable: true,
+                   renderer: Proxmox.Utils.format_boolean,
+                   dataIndex: 'privsep'
+               },
+           ],
+           listeners: {
+               activate: reload,
+               itemdblclick: run_editor
+           }
+       });
+
+       me.callParent();
+    }
+});
diff --git a/www/manager6/form/TokenSelector.js b/www/manager6/form/TokenSelector.js
new file mode 100644 (file)
index 0000000..932ecd7
--- /dev/null
@@ -0,0 +1,91 @@
+Ext.define('PVE.form.TokenSelector', {
+    extend: 'Proxmox.form.ComboGrid',
+    alias: ['widget.pveTokenSelector'],
+
+    allowBlank: false,
+    autoSelect: false,
+    valueField: 'id',
+    displayField: 'id',
+
+    editable: true,
+    anyMatch: true,
+    forceSelection: true,
+
+    initComponent: function() {
+       var me = this;
+
+       var store = new Ext.data.Store({
+           model: 'pve-tokens',
+           sorters: [{
+               property: 'userid'
+           },
+           {
+               property: 'tokenid'
+           }]
+       });
+
+       Ext.apply(me, {
+           store: store,
+            listConfig: {
+               columns: [
+                   {
+                       header: gettext('API Token'),
+                       sortable: true,
+                       dataIndex: 'id',
+                       flex: 1
+                   },
+                   {
+                       header: gettext('Comment'),
+                       sortable: false,
+                       dataIndex: 'comment',
+                       renderer: Ext.String.htmlEncode,
+                       flex: 1
+                   }
+               ]
+           }
+       });
+
+       me.callParent();
+
+       Proxmox.Utils.API2Request({
+           url: '/access/users/?full=1',
+           method: 'GET',
+           failure: function(response, opts) {
+               Proxmox.Utils.setErrorMask(me, response.htmlStatus);
+               me.load_task.delay(me.load_delay);
+           },
+           success: function(response, opts) {
+               Proxmox.Utils.setErrorMask(me, false);
+               var result = Ext.decode(response.responseText);
+               var data = result.data || [];
+               var records = [];
+               Ext.Array.each(data, function(user) {
+                   tokens = user.tokens || [];
+                   Ext.Array.each(tokens, function(token) {
+                       var r = {};
+                       r.id = user.userid + '!' + token.tokenid;
+                       r.comment = token.comment;
+                       records.push(r);
+                   });
+               });
+               store.loadData(records);
+           },
+       });
+    }
+
+}, function() {
+
+    Ext.define('pve-tokens', {
+       extend: 'Ext.data.Model',
+       fields: [
+           'id', 'userid', 'tokenid', 'comment',
+           { type: 'boolean', name: 'privsep' },
+           { type: 'date', dateFormat: 'timestamp', name: 'expire' }
+       ],
+       idProperty: 'id'
+    });
+
+});
+
+
+