From f294ee08a56d1588647da102946a1ddadea8d856 Mon Sep 17 00:00:00 2001 From: Andrew Dodd Date: Tue, 17 Dec 2024 12:37:35 +1100 Subject: [PATCH] luci: Make password reveal work with passsword managers Password managers (like LastPass etc) tend to add additional elements into the DOM for their own context menus. If this happens between the hide/reveal button and the password input, then the logic to reveal the password breaks. This change updates the onclick handler to look backward in the DOM for the first sibling that is an input, and to then toggle the password/text type on that element. Signed-off-by: Andrew Dodd --- .../luasrc/view/dockerman/cbi/inlinevalue.htm | 2 +- .../luci-base/htdocs/luci-static/resources/ui.js | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm b/applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm index e4b0cf7a080b..3ae5d3f9bb47 100644 --- a/applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm +++ b/applications/luci-app-dockerman/luasrc/view/dockerman/cbi/inlinevalue.htm @@ -28,6 +28,6 @@ ifattr(#self.keylist > 0, "data-choices", { self.keylist, self.vallist }) %> /> <%- if self.password then -%> -
+
<% end %> diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js index bff9acc3c002..7e04c6506325 100644 --- a/modules/luci-base/htdocs/luci-static/resources/ui.js +++ b/modules/luci-base/htdocs/luci-static/resources/ui.js @@ -384,8 +384,18 @@ const UITextfield = UIElement.extend(/** @lends LuCI.ui.Textfield.prototype */ { 'title': _('Reveal/hide password'), 'aria-label': _('Reveal/hide password'), 'click': function(ev) { - const e = this.previousElementSibling; - e.type = (e.type === 'password') ? 'text' : 'password'; + let e = this.previousElementSibling; + // DOM manipulation (e.g. by password managers) may have inserted other + // elements between the reveal button and the input. This searches for + // the first previous sibling that is also an input. + while (e && e.tagName !== 'INPUT') { + e = e.previousElementSibling; + } + if (e) { + e.type = (e.type === 'password') ? 'text' : 'password'; + } else { + console.error("unable to find input corresponding to reveal/hide button"); + } ev.preventDefault(); } }, '∗')