Plugin permission ModernUI fixes and name collision issue fix (#7693)

* Fix modernUI plugin permissions loading/saving * Fix partial permission collisions when user/group is a substring of another user/group * line ending fixes

ryanblenis committed Mar 18, 2026 at 04:23 UTC 62fadf14bd83de18e35ee00f25e9ee0918881bfb
2 files changed +20 -21
views/default.handlebars
+2 -2
@@ -19672,13 +19672,13 @@
19672 document.getElementById(listId).style.display = 'none';
19673
19674 var existingTags = container.querySelectorAll('span');
19675 + var tagId = 'perm_tag_' + entityId.replace(/[^a-zA-Z0-9]/g, '_') + '_' + permKey + '_' + level + '_' + accessType + (parentId ? '_' + parentId : '');
19676 for (var i = 0; i < existingTags.length; i++) {
19676 - if (existingTags[i].id && existingTags[i].id.includes(entityId.replace(/[^a-zA-Z0-9]/g, '_'))) {
19677 + if (existingTags[i].id && existingTags[i].id == tagId) {
19678 return;
19679 }
19680 }
19681
19681 - var tagId = 'perm_tag_' + entityId.replace(/[^a-zA-Z0-9]/g, '_') + '_' + permKey + '_' + level + '_' + accessType + (parentId ? '_' + parentId : '');
19682 var tagHtml = '<span style="background:#6c757d; color:#fff; padding:3px 8px; border-radius:3px; font-size:12px;" id="' + tagId + '" data-actualid="' + EscapeHtml(entityId) + '">' + entityIcon + ' ' + EscapeHtml(entityName) + ' <span style="cursor:pointer; margin-left:5px;" onclick="removePermTag(\'' + entityId + '\', \'' + permKey + '\', \'' + level + '\', \'' + accessType + '\', \'' + entityType + '\', \'' + (parentId || '') + '\')">×</span></span>';
19683 container.insertAdjacentHTML('beforeend', tagHtml);
19684
views/default3.handlebars
+18 -19
@@ -4576,22 +4576,6 @@
4576 pluginHandler.refreshPluginHandler();
4577 break;
4578 }
4579 - case 'pluginPermissions': {
4580 - handlePluginPermissions(message.event);
4581 - break;
4582 - }
4583 - case 'pluginPermissionsSet': {
4584 - if (message.event.success) {
4585 - alert("Permissions saved successfully");
4586 - } else {
4587 - alert("Error saving permissions: " + message.event.error);
4588 - }
4589 - break;
4590 - }
4591 - case 'pluginPermissionList': {
4592 - handlePluginPermissionList(message.event);
4593 - break;
4594 - }
4579 case 'plugin': {
4580 if (pluginHandler == null) break;
4581 try { pluginHandler[message.event.plugin][message.event.pluginaction](message); } catch (e) { console.log("PluginHandler could not event message: ", e); }
@@ -4603,6 +4587,22 @@
4587 }
4588 break;
4589 }
4590 + case 'pluginPermissions': {
4591 + handlePluginPermissions(message);
4592 + break;
4593 + }
4594 + case 'pluginPermissionsSet': {
4595 + if (message.success) {
4596 + alert("Permissions saved successfully");
4597 + } else {
4598 + alert("Error saving permissions: " + message.error);
4599 + }
4600 + break;
4601 + }
4602 + case 'pluginPermissionList': {
4603 + handlePluginPermissionList(message);
4604 + break;
4605 + }
4606 case 'createInviteLink': { // Agent installation invitation link
4607 if (xxdialogTag != message.meshid) break;
4608 var servername = serverinfo.name;
@@ -21432,14 +21432,14 @@
21432
21433 // Check if already exists
21434 var existingTags = container.querySelectorAll('span');
21435 + var tagId = 'perm_tag_' + entityId.replace(/[^a-zA-Z0-9]/g, '_') + '_' + permKey + '_' + level + '_' + accessType + (parentId ? '_' + parentId : '');
21436 for (var i = 0; i < existingTags.length; i++) {
21436 - if (existingTags[i].id && existingTags[i].id.includes(entityId.replace(/[^a-zA-Z0-9]/g, '_'))) {
21437 + if (existingTags[i].id && existingTags[i].id == tagId) {
21438 return; // Already added
21439 }
21440 }
21441
21442 // Add new tag
21442 - var tagId = 'perm_tag_' + entityId.replace(/[^a-zA-Z0-9]/g, '_') + '_' + permKey + '_' + level + '_' + accessType + (parentId ? '_' + parentId : '');
21443 var tagHtml = '<span class="badge" style="background:#6c757d; padding:5px 8px; font-size:12px;" id="' + tagId + '" data-actualid="' + EscapeHtml(entityId) + '">' + entityIcon + ' ' + EscapeHtml(entityName) + ' <i class="fa-solid fa-times" style="cursor:pointer; margin-left:5px;" onclick="removePermTag(\'' + entityId + '\', \'' + permKey + '\', \'' + level + '\', \'' + accessType + '\', \'' + entityType + '\', \'' + (parentId || '') + '\')"></i></span>';
21444 container.insertAdjacentHTML('beforeend', tagHtml);
21445
@@ -21702,7 +21702,6 @@
21702 });
21703
21704 closePluginPermModal();
21705 - alert('Permissions saved successfully');
21705 }
21706
21707 //