diff --git a/www/Makefile b/www/Makefile index 62c44516..12a195ef 100644 --- a/www/Makefile +++ b/www/Makefile @@ -7,7 +7,9 @@ IMAGES := \ JSSRC= \ form/UserSelector.js \ config/UserView.js \ + config/ACLView.js \ window/UserEdit.js \ + window/ACLEdit.js \ Utils.js \ LoginView.js \ VersionInfo.js \ diff --git a/www/NavigationTree.js b/www/NavigationTree.js index c1bf0593..6761e6b4 100644 --- a/www/NavigationTree.js +++ b/www/NavigationTree.js @@ -24,6 +24,12 @@ Ext.define('PBS.store.NavigationStore', { path: 'pbsUserView', leaf: true }, + { + text: gettext('Permissions'), + iconCls: 'fa fa-unlock', + path: 'pbsACLView', + leaf: true + }, { text: gettext('Data Store'), iconCls: 'fa fa-archive', diff --git a/www/config/ACLView.js b/www/config/ACLView.js new file mode 100644 index 00000000..199f5a1d --- /dev/null +++ b/www/config/ACLView.js @@ -0,0 +1,142 @@ +Ext.define('pmx-acls', { + extend: 'Ext.data.Model', + fields: [ + 'path', 'ugid', 'ugid_type', 'roleid', 'propagate', + { + name: 'aclid', + calculate: function(data) { + return `${data.path} for ${data.ugid}`; + }, + }, + ], + idProperty: 'aclid', + proxy: { + type: 'proxmox', + url: '/api2/json/access/acl', + }, +}); + +Ext.define('PBS.config.ACLView', { + extend: 'Ext.grid.GridPanel', + alias: 'widget.pbsACLView', + + stateful: true, + stateId: 'grid-acls', + + title: gettext('ACLs'), + + + aclPath: undefined, + aclExact: undefined, + + controller: { + xclass: 'Ext.app.ViewController', + + addACL: function() { + let me = this; + let view = me.getView(); + Ext.create('PBS.window.ACLEdit', { + path: view.aclPath, + listeners: { + destroy: function() { + me.reload(); + }, + }, + }).show(); + }, + + removeACL: function(btn, event, rec) { + let me = this; + Proxmox.Utils.API2Request({ + url:'/access/acl', + method: 'PUT', + params: { + 'delete': 1, + path: rec.data.path, + role: rec.data.roleid, + userid: rec.data.ugid, + }, + callback: function() { + me.reload(); + }, + failure: function (response, opts) { + Ext.Msg.alert(gettext('Error'), response.htmlStatus); + }, + }); + }, + + reload: function() { this.getView().getStore().rstore.load(); }, + + init: function(view) { + let proxy = view.getStore().rstore.getProxy(); + + let params = {}; + if (view.aclPath !== undefined) { + params.path = view.aclPath; + } + if (view.aclExact !== undefined) { + params.exact = view.aclExact; + } + proxy.setExtraParams(params); + }, + }, + + store: { + type: 'diff', + autoDestroy: true, + autoDestroyRstore: true, + sorters: 'userid', + rstore: { + type: 'update', + storeid: 'pmx-acls', + model: 'pmx-acls', + autoStart: true, + interval: 5000, + }, + }, + + tbar: [ + { + xtype: 'proxmoxButton', + text: gettext('Add'), + handler: 'addACL', + selModel: false, + }, + { + xtype: 'proxmoxStdRemoveButton', + handler: 'removeACL', + callback: 'reload', + }, + ], + + columns: [ + { + header: gettext('Path'), + width: 200, + sortable: true, + renderer: Ext.String.htmlEncode, + dataIndex: 'path', + }, + { + header: gettext('User/Group'), + width: 100, + sortable: true, + renderer: Ext.String.htmlEncode, + dataIndex: 'ugid', + }, + { + header: gettext('Role'), + width: 80, + sortable: true, + dataIndex: 'roleid', + }, + { + header: gettext('Propagate'), + width: 150, + sortable: true, + renderer: Proxmox.Utils.format_boolean, + dataIndex: 'propagate', + }, + ], + +}); diff --git a/www/window/ACLEdit.js b/www/window/ACLEdit.js new file mode 100644 index 00000000..ba7a7f86 --- /dev/null +++ b/www/window/ACLEdit.js @@ -0,0 +1,57 @@ +Ext.define('PBS.window.ACLEdit', { + extend: 'Proxmox.window.Edit', + alias: 'widget.pbsACLAdd', + mixins: ['Proxmox.Mixin.CBind'], + + url: '/access/acl', + method: 'PUT', + isAdd: true, + isCreate: true, + + // caller can give a static path + path: undefined, + + subject: gettext('User Permission'), + + getValues: function(dirtyOnly) { + let me = this; + let values = me.callParent(arguments); + + if (me.path) { + values.path = me.path; + } + return values; + }, + + items: [ + { + xtype: 'pmxDisplayEditField', + fieldLabel: gettext('Path'), + cbind: { + editable: '{!path}', + value: '{path}', + }, + name: 'path', + allowBlank: false, + }, + { + xtype: 'pbsUserSelector', + fieldLabel: gettext('User'), + name: 'userid', + allowBlank: false, + }, + { + xtype: 'pmxRoleSelector', + name: 'role', + value: 'NoAccess', + fieldLabel: gettext('Role'), + }, + { + xtype: 'proxmoxcheckbox', + name: 'propagate', + checked: true, + uncheckedValue: 0, + fieldLabel: gettext('Propagate'), + }, + ], +});