From 0331cb976a245db92961b35b944e71c473809397 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sun, 2 Aug 2026 12:55:19 -0400 Subject: [PATCH 1/2] fix: resolve discovery and UI bugs --- nodejs/plugins/discovery/nmap.js | 12 +++++++----- nodejs/plugins/discovery/proxmox.js | 3 +++ nodejs/views/discovery.ejs | 2 +- nodejs/views/plugins.ejs | 15 +++++++++++++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/nodejs/plugins/discovery/nmap.js b/nodejs/plugins/discovery/nmap.js index 6f5b90b..d0eba1e 100644 --- a/nodejs/plugins/discovery/nmap.js +++ b/nodejs/plugins/discovery/nmap.js @@ -31,17 +31,19 @@ module.exports = { if (!targetRange) throw new Error("Missing targetRange for Nmap"); return new Promise((resolve, reject) => { - const scan = new nmap.OsAndPortScan(targetRange); + // OsAndPortScan requires root (for -O). NmapScan does a basic port scan (TCP connect if non-root). + const scan = new nmap.NmapScan(targetRange); scan.command.push('-Pn'); scan.on('complete', function(data) { const resources = []; const edges = []; for (const host of data) { - if (!host.mac || !host.ip) continue; - const hostSlug = `nmap-host-${host.mac.replace(/:/g, '')}`; + if (!host.ip) continue; + const hostId = host.mac ? host.mac.replace(/:/g, '') : host.ip.replace(/\\./g, '_'); + const hostSlug = `nmap-host-${hostId}`; - const interfaces = [{ mac: host.mac, ip: host.ip }]; + const interfaces = [{ mac: host.mac || null, ip: host.ip }]; resources.push({ kind: 'host', @@ -52,7 +54,7 @@ module.exports = { if (host.openPorts && host.openPorts.length > 0) { for (const port of host.openPorts) { - const svcSlug = `nmap-svc-${host.mac.replace(/:/g, '')}-${port.port}`; + const svcSlug = `nmap-svc-${hostId}-${port.port}`; resources.push({ kind: 'service', name: `${port.service} on ${port.port}`, diff --git a/nodejs/plugins/discovery/proxmox.js b/nodejs/plugins/discovery/proxmox.js index 25c691d..e59713d 100644 --- a/nodejs/plugins/discovery/proxmox.js +++ b/nodejs/plugins/discovery/proxmox.js @@ -43,6 +43,9 @@ module.exports = { const headers = { 'Authorization': `PVEAPIToken=${tokenId}=${tokenSecret}` }; + + // Ensure URL has no trailing slash + url = url.replace(/\\/+$/, ''); const resources = []; const edges = []; diff --git a/nodejs/views/discovery.ejs b/nodejs/views/discovery.ejs index 05e225b..2992eea 100644 --- a/nodejs/views/discovery.ejs +++ b/nodejs/views/discovery.ejs @@ -164,7 +164,7 @@ return; } $('.actionMessage').html('
Successfully promoted! Created groups: ' + res.groups.join(', ') + '
').show(); - renderTable(); + loadResources(); }); } diff --git a/nodejs/views/plugins.ejs b/nodejs/views/plugins.ejs index 3ce1724..ab691f3 100644 --- a/nodejs/views/plugins.ejs +++ b/nodejs/views/plugins.ejs @@ -57,6 +57,7 @@ + {{#lastError}}{{/lastError}} {{#enabled}}{{/enabled}} {{^enabled}}{{/enabled}} @@ -280,7 +281,7 @@ '
Secret fields are edited separately with the button.
', footer: { metaHtml: app.modal.formatAudit ? app.modal.formatAudit(p, { formatDate: function(ms){ return moment(ms).format('YYYY-MM-DD HH:mm'); } }) : '', - buttonsHtml: app.modal.footerButtons({ onSave: 'saveEdit("' + id + '")', saveLabel: 'Save' }) + buttonsHtml: app.modal.footerButtons({ onSave: 'saveEdit(\'' + id + '\')', saveLabel: 'Save' }) } }); } @@ -324,7 +325,7 @@ app.modal.open({ title: 'Edit Secrets — ' + p.name, bodyHtml: html, - footer: { buttonsHtml: app.modal.footerButtons({ onSave: 'saveSecrets("' + id + '")', saveLabel: 'Save Secrets' }) } + footer: { buttonsHtml: app.modal.footerButtons({ onSave: 'saveSecrets(\'' + id + '\')', saveLabel: 'Save Secrets' }) } }); } @@ -369,6 +370,16 @@ } } + function showLogs(id) { + var p = pluginsById[id]; + if (!p || !p.lastError) return; + app.modal.open({ + title: 'Logs — ' + p.name, + bodyHtml: '
' + String(p.lastError).replace(//g, '>') + '
', + footer: { buttonsHtml: '' } + }); + } + async function togglePlugin(id, enable) { try { await app.api.post('plugins/' + id + (enable ? '/load' : '/unload'), {}); From 230e5be2fdb0b88f5a8ff8b83abe8a241057ce39 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sun, 2 Aug 2026 13:20:15 -0400 Subject: [PATCH 2/2] fix: regex syntax error in proxmox plugin --- nodejs/config/inventory.sqlite | Bin 69632 -> 69632 bytes nodejs/plugins/discovery/proxmox.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/nodejs/config/inventory.sqlite b/nodejs/config/inventory.sqlite index eb5adfc8c752193341446fea3b5e72ddd2aa263b..7cc5e8e3d470e9ac5b8dbd369a0fff32a307ed40 100644 GIT binary patch delta 2637 zcma)8O>7%g5MI|QaqP8|DhV`+leol14b@BDd;5MX(Et)sa*HB-K!DnPKPwOxIV2Yn zRc;P&14{RRKtdEz6~qAvSt>sV1e`d43I|l+1{W?|=?M^Ti|utnV%D~7k7hLA{CqRB zm#+<7zBY7a`dF^?TJ=%){n5p#sXCX!C}}Z}Ofo=J5CJ8L29ZD%5rT1OZ2Z<#9Y_Qj zr4nCwW^-#B=ofU;0=0VyL(Bja0OA_r=iGUeFsUg%=Qk4#LC9q`TK6Su}!Q{Rl$&O&$&LeCpI-k4l?+B>nf z<|VI?sR$|uf~AX*5b0900=pzBi4e7tA{Ku+asLSG;nilQimB^(?AAmdQjj9$pKQ!5 z>J*9E5HhF%7lHu7sRe?g0ECFyP$_H_mhsy&i)mut%~Ycvkl?VB!(r7-wVrqE{e2k< ziZGUl0tRsi2z8}ZOk%)|B@i)+TsZOEz5N+ps!lza0#iH)nBw@0>d89ChBE9p!FUKA z3WPw=&;VkoF@~GaauxqsU1)X7cwy_=Z3~{aTiezg&JYohLBKt&=j9&XmvMlRa+P*@ z2Es)kH3QOc1dwE5!9-dcX=Qw4b|EeG_p?)JsW~46oN66?KG+AWFlHhW7RZ2UKt$mF zDaZSOTLS|~2n%JrKG%o4JJ(lfj>Uk4owoh?+Q`~28pjqdh2?<^OyG^Txf`Rhu` zi1*GvkP1Ka3;C7PsRpi`Nrj93nwR^9&-#S+Z!5E7`Q^e+JiI>taABty6@MxJUir1W zT71aA<1ZFJDST7;)ZZnZ$5GL#;M{fUb$HF zMz4<6D>o~v<)6z<|2hBf(qE-lOQ(vpV%yc=W}&r5&~W3vMq_O)OC^#EwUuRXvdm1f zl3V*P99x3;=rz)>-6OCQcb3N7jr*{eS_iM>p~>xyC19Q_(g3jLT^nzpO^+%61_bf= zffMgigvl9hbuLLFcaNk0lXu#+${`GBRWoU)H`t~}>~0kQ4PrB68=A`;*NylG8lA{dfMjMZm+^X3H|Yo IpL;3)4`GIS$^ZZW delta 1538 zcma)+PiRy}9LL|=P0Vigy|)$;<0hLwG~3cNPMmr3=gp*TqJrq&f^-X|t@`H83`(R$ zlZy?a9(okihb$IKJxE)65M;qWIf(V-MbLwYz3HWg_MDT5vx(W=K+$~@x!##y^m-e=dFM@yxO(jkM`BtS|c0g*@mp$!8{5*%vAcq~ZzOQ|wM zp`e^c(UD_6EG>iNbaFxixpJlseRnWJVEt0ymU_huA~5xbcUBmb%EZV@YN!A~+JHEW z1&~@>Wf~DdXj&bv}QLR{iZfDm9z*d zQP5DKfI%z-M6d{O0wqXg9C4wk z04ikI0%QbYoLGucl9GsNl$Li?Iu3BAym5dGMCr*#rESQ{BbweX@2n&gQ)Q9_AZ4r; z)v+zsR!mfED1y?UkfpE6lRGxMab)TEvIgJlrDd%)rZ|v=5UqE9kJW{!Rkr)(ma>gh z+;#&2E)BQil?23EVi5DlwucFh!}R3PWJldkMoS)Kvrx<;K4V?fgp}uKyYtSUTL>gX zNys$>2s2BFA+=Msiwq;lu#QZERJt%W+3x(xSSJDFbwUQ?#=Wrx*9%^@-^TF7kHOh) zT%UIwcf1=L=d2yqy76P5O?=d})!Fy?YMafx{(gTb*=rM5x*2|tO+2(Yy8Z8%U6{3* zQ{9Z9@oe|Qpgn`%=RR%+PdkI`{73B_IR8mIING^$p)*+R2pa#)k8aO?nm>^CEsV2% z)BnQ%FL>!6?Ek`B^QQXm1b4j^|L0&Z{~&+0aHH^3;h8^P_}05#ECd%lCz$gN6-fh4 z{F`eW_c_D^_=-fNptDCEwQU46BoTCM)Vb4S0TTtRIh z)Xht8sTZh`MD)cZ;(!T?)2eq{`+74`Rz>^r&g`f7)#!~4Kb$#kR;N8W4j2- KZZCT7mFyc@GK13q diff --git a/nodejs/plugins/discovery/proxmox.js b/nodejs/plugins/discovery/proxmox.js index e59713d..8261bd0 100644 --- a/nodejs/plugins/discovery/proxmox.js +++ b/nodejs/plugins/discovery/proxmox.js @@ -45,7 +45,7 @@ module.exports = { }; // Ensure URL has no trailing slash - url = url.replace(/\\/+$/, ''); + url = url.endsWith('/') ? url.slice(0, -1) : url; const resources = []; const edges = [];