From: Alexandre Derumier <aderumier@odiso.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH v3 pve-manager 3/4] ui: add vnet permissions panel
Date: Tue, 6 Jun 2023 15:19:26 +0200 [thread overview]
Message-ID: <20230606131927.1667420-10-aderumier@odiso.com> (raw)
In-Reply-To: <20230606131927.1667420-1-aderumier@odiso.com>
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
www/manager6/Makefile | 2 +
www/manager6/sdn/Browser.js | 17 +-
www/manager6/sdn/VnetACLView.js | 289 +++++++++++++++++++++++++++
www/manager6/sdn/ZoneContentPanel.js | 41 ++++
www/manager6/sdn/ZoneContentView.js | 25 ++-
5 files changed, 356 insertions(+), 18 deletions(-)
create mode 100644 www/manager6/sdn/VnetACLView.js
create mode 100644 www/manager6/sdn/ZoneContentPanel.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 2b577c8e..fb9930af 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -251,10 +251,12 @@ JSSRC= \
sdn/StatusView.js \
sdn/VnetEdit.js \
sdn/VnetView.js \
+ sdn/VnetACLView.js \
sdn/VnetPanel.js \
sdn/SubnetEdit.js \
sdn/SubnetView.js \
sdn/ZoneContentView.js \
+ sdn/ZoneContentPanel.js \
sdn/ZoneView.js \
sdn/OptionsPanel.js \
sdn/controllers/Base.js \
diff --git a/www/manager6/sdn/Browser.js b/www/manager6/sdn/Browser.js
index 09b0c4fe..3dc5a5ad 100644
--- a/www/manager6/sdn/Browser.js
+++ b/www/manager6/sdn/Browser.js
@@ -25,14 +25,15 @@ Ext.define('PVE.sdn.Browser', {
const caps = Ext.state.Manager.get('GuiCap');
- if (caps.sdn['SDN.Audit']) {
- me.items.push({
- xtype: 'pveSDNZoneContentView',
- title: gettext('Content'),
- iconCls: 'fa fa-th',
- itemId: 'content',
- });
- }
+ me.items.push({
+ nodename: nodename,
+ zone: sdnId,
+ xtype: 'pveSDNZoneContentPanel',
+ title: gettext('Content'),
+ iconCls: 'fa fa-th',
+ itemId: 'content',
+ });
+
if (caps.sdn['Permissions.Modify']) {
me.items.push({
xtype: 'pveACLView',
diff --git a/www/manager6/sdn/VnetACLView.js b/www/manager6/sdn/VnetACLView.js
new file mode 100644
index 00000000..af10d954
--- /dev/null
+++ b/www/manager6/sdn/VnetACLView.js
@@ -0,0 +1,289 @@
+Ext.define('PVE.sdn.VnetACLAdd', {
+ extend: 'Proxmox.window.Edit',
+ alias: ['widget.pveSDNVnetACLAdd'],
+
+ url: '/access/acl',
+ method: 'PUT',
+ isAdd: true,
+ isCreate: true,
+
+ width: 400,
+ initComponent: function() {
+ let me = this;
+
+ let items = [
+ {
+ xtype: 'hiddenfield',
+ name: 'path',
+ value: me.path,
+ allowBlank: false,
+ fieldLabel: gettext('Path'),
+ },
+ ];
+
+ if (me.aclType === 'group') {
+ me.subject = gettext("Group Permission");
+ items.push({
+ xtype: 'pveGroupSelector',
+ name: 'groups',
+ fieldLabel: gettext('Group'),
+ });
+ } else if (me.aclType === 'user') {
+ me.subject = gettext("User Permission");
+ items.push({
+ xtype: 'pmxUserSelector',
+ name: 'users',
+ fieldLabel: gettext('User'),
+ });
+ } else if (me.aclType === 'token') {
+ me.subject = gettext("API Token Permission");
+ items.push({
+ xtype: 'pveTokenSelector',
+ name: 'tokens',
+ fieldLabel: gettext('API Token'),
+ });
+ } else {
+ throw "unknown ACL type";
+ }
+
+ items.push({
+ xtype: 'pmxRoleSelector',
+ name: 'roles',
+ value: 'NoAccess',
+ fieldLabel: gettext('Role'),
+ });
+
+ items.push({
+ xtype: 'proxmoxintegerfield',
+ name: 'vlan',
+ minValue: 1,
+ maxValue: 4096,
+ allowBlank: true,
+ fieldLabel: 'Vlan',
+ emptyText: gettext('All'),
+ });
+
+ let ipanel = Ext.create('Proxmox.panel.InputPanel', {
+ items: items,
+ onlineHelp: 'pveum_permission_management',
+ onGetValues: function(values) {
+ if (values.vlan) {
+ values.path = values.path + "/" + values.vlan;
+ delete values.vlan;
+ }
+ return values;
+ },
+ });
+
+ Ext.apply(me, {
+ items: [ipanel],
+ });
+
+ me.callParent();
+ },
+});
+
+Ext.define('PVE.sdn.VnetACLView', {
+ extend: 'Ext.grid.GridPanel',
+
+ alias: ['widget.pveSDNVnetACLView'],
+
+ onlineHelp: 'chapter_user_management',
+
+ stateful: true,
+ stateId: 'grid-acls',
+
+ // use fixed path
+ path: undefined,
+
+ setPath: function(path) {
+ let me = this;
+
+ me.path = path;
+
+ if (path === undefined) {
+ me.down('#groupmenu').setDisabled(true);
+ me.down('#usermenu').setDisabled(true);
+ me.down('#tokenmenu').setDisabled(true);
+ } else {
+ me.down('#groupmenu').setDisabled(false);
+ me.down('#usermenu').setDisabled(false);
+ me.down('#tokenmenu').setDisabled(false);
+ me.store.load();
+ }
+ },
+ initComponent: function() {
+ let me = this;
+
+ let store = Ext.create('Ext.data.Store', {
+ model: 'pve-acl',
+ proxy: {
+ type: 'proxmox',
+ url: "/api2/json/access/acl",
+ },
+ sorters: {
+ property: 'path',
+ direction: 'ASC',
+ },
+ });
+
+ store.addFilter(Ext.create('Ext.util.Filter', {
+ filterFn: item => item.data.path.replace(/(\/sdn\/zones\/(.*)\/(.*))\/[0-9]*$/, '$1') === me.path,
+ }));
+
+ let render_ugid = function(ugid, metaData, record) {
+ if (record.data.type === 'group') {
+ return '@' + ugid;
+ }
+
+ return Ext.String.htmlEncode(ugid);
+ };
+
+ let render_vlan = function(path, metaData, record) {
+ let vlan = 'any';
+ const match = path.match(/(\/sdn\/zones\/)(.*)\/(.*)\/([0-9]*)$/);
+ if (match) {
+ vlan = match[4];
+ }
+
+ return Ext.String.htmlEncode(vlan);
+ };
+
+ let columns = [
+ {
+ header: gettext('User') + '/' + gettext('Group') + '/' + gettext('API Token'),
+ flex: 1,
+ sortable: true,
+ renderer: render_ugid,
+ dataIndex: 'ugid',
+ },
+ {
+ header: gettext('Role'),
+ flex: 1,
+ sortable: true,
+ dataIndex: 'roleid',
+ },
+ {
+ header: gettext('Vlan'),
+ flex: 1,
+ sortable: true,
+ renderer: render_vlan,
+ dataIndex: 'path',
+ },
+ ];
+
+
+ let sm = Ext.create('Ext.selection.RowModel', {});
+
+ let remove_btn = new Proxmox.button.Button({
+ text: gettext('Remove'),
+ disabled: true,
+ selModel: sm,
+ confirmMsg: gettext('Are you sure you want to remove this entry'),
+ handler: function(btn, event, rec) {
+ var params = {
+ 'delete': 1,
+ path: rec.data.path,
+ roles: rec.data.roleid,
+ };
+ if (rec.data.type === 'group') {
+ params.groups = rec.data.ugid;
+ } else if (rec.data.type === 'user') {
+ params.users = rec.data.ugid;
+ } else if (rec.data.type === 'token') {
+ params.tokens = rec.data.ugid;
+ } else {
+ throw 'unknown data type';
+ }
+
+ Proxmox.Utils.API2Request({
+ url: '/access/acl',
+ params: params,
+ method: 'PUT',
+ waitMsgTarget: me,
+ callback: () => store.load(),
+ failure: response => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+ });
+ },
+ });
+
+ Proxmox.Utils.monStoreErrors(me, store);
+
+ Ext.apply(me, {
+ store: store,
+ selModel: sm,
+ tbar: [
+ {
+ text: gettext('Add'),
+ menu: {
+ xtype: 'menu',
+ items: [
+ {
+ text: gettext('Group Permission'),
+ disabled: !me.path,
+ itemId: 'groupmenu',
+ iconCls: 'fa fa-fw fa-group',
+ handler: function() {
+ var win = Ext.create('PVE.sdn.VnetACLAdd', {
+ aclType: 'group',
+ path: me.path,
+ });
+ win.on('destroy', () => store.load());
+ win.show();
+ },
+ },
+ {
+ text: gettext('User Permission'),
+ disabled: !me.path,
+ itemId: 'usermenu',
+ iconCls: 'fa fa-fw fa-user',
+ handler: function() {
+ var win = Ext.create('PVE.sdn.VnetACLAdd', {
+ aclType: 'user',
+ path: me.path,
+ });
+ win.on('destroy', () => store.load());
+ win.show();
+ },
+ },
+ {
+ text: gettext('API Token Permission'),
+ disabled: !me.path,
+ itemId: 'tokenmenu',
+ iconCls: 'fa fa-fw fa-user-o',
+ handler: function() {
+ let win = Ext.create('PVE.sdn.VnetACLAdd', {
+ aclType: 'token',
+ path: me.path,
+ });
+ win.on('destroy', () => store.load());
+ win.show();
+ },
+ },
+ ],
+ },
+ },
+ remove_btn,
+ ],
+ viewConfig: {
+ trackOver: false,
+ },
+ columns: columns,
+ listeners: {
+ },
+ });
+
+ me.callParent();
+ },
+}, function() {
+ Ext.define('pve-acl-vnet', {
+ extend: 'Ext.data.Model',
+ fields: [
+ 'path', 'type', 'ugid', 'roleid',
+ {
+ name: 'propagate',
+ type: 'boolean',
+ },
+ ],
+ });
+});
diff --git a/www/manager6/sdn/ZoneContentPanel.js b/www/manager6/sdn/ZoneContentPanel.js
new file mode 100644
index 00000000..5bb081bb
--- /dev/null
+++ b/www/manager6/sdn/ZoneContentPanel.js
@@ -0,0 +1,41 @@
+Ext.define('PVE.sdn.ZoneContentPanel', {
+ extend: 'Ext.panel.Panel',
+ alias: 'widget.pveSDNZoneContentPanel',
+
+ title: 'Vnet',
+
+ onlineHelp: 'pvesdn_config_vnet',
+
+ initComponent: function() {
+ var me = this;
+
+ var permissions_panel = Ext.createWidget('pveSDNVnetACLView', {
+ title: gettext('Vnet Permissions'),
+ region: 'center',
+ border: false,
+ });
+
+ var vnetview_panel = Ext.createWidget('pveSDNZoneContentView', {
+ title: 'Vnets',
+ region: 'west',
+ permissions_panel: permissions_panel,
+ nodename: me.nodename,
+ zone: me.zone,
+ width: '50%',
+ border: false,
+ split: true,
+ });
+
+ Ext.apply(me, {
+ layout: 'border',
+ items: [vnetview_panel, permissions_panel],
+ listeners: {
+ show: function() {
+ permissions_panel.fireEvent('show', permissions_panel);
+ },
+ },
+ });
+
+ me.callParent();
+ },
+});
diff --git a/www/manager6/sdn/ZoneContentView.js b/www/manager6/sdn/ZoneContentView.js
index 1ea65450..4bc92718 100644
--- a/www/manager6/sdn/ZoneContentView.js
+++ b/www/manager6/sdn/ZoneContentView.js
@@ -17,17 +17,15 @@ Ext.define('PVE.sdn.ZoneContentView', {
initComponent: function() {
var me = this;
- var nodename = me.pveSelNode.data.node;
- if (!nodename) {
+ if (!me.nodename) {
throw "no node name specified";
}
- var zone = me.pveSelNode.data.sdn;
- if (!zone) {
+ if (!me.zone) {
throw "no zone ID specified";
}
- var baseurl = "/nodes/" + nodename + "/sdn/zones/" + zone + "/content";
+ var baseurl = "/nodes/" + me.nodename + "/sdn/zones/" + me.zone + "/content";
var store = Ext.create('Ext.data.Store', {
model: 'pve-sdnzone-content',
groupField: 'content',
@@ -48,7 +46,6 @@ Ext.define('PVE.sdn.ZoneContentView', {
};
Proxmox.Utils.monStoreErrors(me, store);
-
Ext.apply(me, {
store: store,
selModel: sm,
@@ -79,11 +76,19 @@ Ext.define('PVE.sdn.ZoneContentView', {
dataIndex: 'statusmsg',
},
],
- listeners: {
- activate: reload,
- },
+ listeners: {
+ activate: reload,
+ show: reload,
+ select: function(_sm, rec) {
+ let path = `/sdn/zones/${me.zone}/${rec.data.vnet}`;
+ me.permissions_panel.setPath(path);
+ },
+ deselect: function() {
+ me.permissions_panel.setPath(undefined);
+ },
+ },
});
-
+ store.load();
me.callParent();
},
}, function() {
--
2.30.2
next prev parent reply other threads:[~2023-06-06 13:20 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-06 13:19 [pve-devel] [PATCH-SERIE pve-access-control/pve-manager/pve-guest-common/qemu-server/pve-network] check permissions on local bridge Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH v2 pve-access-control 1/3] access control: add /sdn/zones/<zone>/<vnet>/<vlan> path Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH v3 qemu-server 1/1] api2: add check_bridge_access for create/update/clone vm Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH v3 pve-manager 1/4] api2: network: check permissions for local bridges Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH pve-network 1/1] get_local_vnets: fix permission path && perm Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH pve-guest-common 1/1] helpers : add check_vnet_access Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH v3 pve-manager 2/4] api2: cluster: ressources: add "localnetwork" zone Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH v2 pve-access-control 2/3] rpcenvironnment: add check_sdn_bridge Alexandre Derumier
2023-06-06 13:19 ` [pve-devel] [PATCH v2 pve-access-control 3/3] add new SDN.use privilege in PVESDNUser role Alexandre Derumier
2023-06-06 13:19 ` Alexandre Derumier [this message]
2023-06-06 13:19 ` [pve-devel] [PATCH v3 pve-manager 4/4] ui: add permissions management for "localnetwork" zone Alexandre Derumier
2023-06-07 12:03 [pve-devel] [PATCH-SERIE pve-access-control/pve-manager/pve-guest-common/qemu-server/pve-network] check permissions on local bridge Alexandre Derumier
2023-06-07 12:03 ` [pve-devel] [PATCH v3 pve-manager 3/4] ui: add vnet permissions panel Alexandre Derumier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230606131927.1667420-10-aderumier@odiso.com \
--to=aderumier@odiso.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox