From b5678b65f16d0bd3231d8b1cd0e0e41980519987 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 29 Oct 2023 11:14:36 +0100 Subject: [PATCH] Add app password support and add robot column to the session table Signed-off-by: DL6ER --- scripts/pi-hole/js/settings-api.js | 68 ++++++++- settings-api.lp | 37 +++++ style/pi-hole.css | 217 +++++++++++++++++++++++++++++ 3 files changed, 320 insertions(+), 2 deletions(-) diff --git a/scripts/pi-hole/js/settings-api.js b/scripts/pi-hole/js/settings-api.js index e498f297..cde5858a 100644 --- a/scripts/pi-hole/js/settings-api.js +++ b/scripts/pi-hole/js/settings-api.js @@ -40,6 +40,7 @@ $(function () { { data: "id" }, { data: "valid", render: renderBool }, { data: null }, + { data: "app", render: renderBool }, { data: "login_at", render: utils.renderTimestamp }, { data: "valid_until", render: utils.renderTimestamp }, { data: "remote_addr", type: "ip-address" }, @@ -84,10 +85,10 @@ $(function () { '">' + '' + ""; - $("td:eq(8)", row).html(button); + $("td:eq(9)", row).html(button); if (data.current_session) { ownSessionID = data.id; - $("td:eq(6)", row).html( + $("td:eq(7)", row).html( '' + data.remote_addr + "" @@ -311,6 +312,69 @@ $("#modal-totp").on("shown.bs.modal", function () { }); }); +var apppwhash = null; +$("#modal-apppw").on("shown.bs.modal", function () { + $.ajax({ + url: "/api/auth/app", + }) + .done(function (data) { + apppwhash = data.app.hash; + $("#password_code").text(data.app.password); + $("#password_display").removeClass("hidden"); + $("#password-spinner").hide(); + }) + .fail(function (data) { + apiFailure(data); + }); +}); + +$("#apppw_submit").on("click", function () { + // Enable app password + setAppPassword(); +}); + +$("#apppw_clear").on("click", function () { + // Disable app password + apppwhash = ""; + setAppPassword(); +}); + +function setAppPassword() { + $.ajax({ + url: "/api/config", + type: "PATCH", + dataType: "json", + processData: false, + data: JSON.stringify({ config: { webserver: { api: { app_pwhash: apppwhash } } } }), + contentType: "application/json", + }) + .done(function () { + $("#modal-apppw").modal("hide"); + const verb = apppwhash.length > 0 ? "enabled" : "disabled"; + const verb2 = apppwhash.length > 0 ? "will" : "may"; + alert( + "App password has been " + + verb + + ", you " + + verb2 + + " need to re-login to continue using the web interface." + ); + location.reload(); + }) + .fail(function (data) { + apiFailure(data); + }); +} + +// Remove class "password_background" from the password input field with ID +// password_code when the user hovers over it or if it is focused +$("#password_code").on("mouseover focus", function () { + $(this).removeClass("password_background"); +}); +$("#password_code").on("mouseout blur", function () { + $(this).addClass("password_background"); +}); + // Trigger keyup event when pasting into the TOTP code input field $("#totp_code").on("paste", function (e) { $(e.target).keyup(); diff --git a/settings-api.lp b/settings-api.lp index dd0cc317..faa122b3 100644 --- a/settings-api.lp +++ b/settings-api.lp @@ -136,8 +136,11 @@ mg.include('scripts/pi-hole/lua/settings_header.lp','r') + +
+
@@ -158,6 +161,7 @@ mg.include('scripts/pi-hole/lua/settings_header.lp','r') ID Valid TLS + Login at Valid until Client IP @@ -217,6 +221,39 @@ mg.include('scripts/pi-hole/lua/settings_header.lp','r') + + diff --git a/style/pi-hole.css b/style/pi-hole.css index 5d73e53d..d83354db 100644 --- a/style/pi-hole.css +++ b/style/pi-hole.css @@ -1173,3 +1173,220 @@ table.dataTable tbody > tr > .selected { .button-pad { margin: 2px; } + +.m-0 { + margin: 0 !important; +} +.m-1 { + margin: 0.25rem !important; +} +.m-2 { + margin: 0.5rem !important; +} +.m-3 { + margin: 1rem !important; +} +.m-4 { + margin: 1.5rem !important; +} +.m-5 { + margin: 3rem !important; +} + +.mt-0 { + margin-top: 0 !important; +} +.mr-0 { + margin-right: 0 !important; +} +.mb-0 { + margin-bottom: 0 !important; +} +.ml-0 { + margin-left: 0 !important; +} +.mx-0 { + margin-left: 0 !important; + margin-right: 0 !important; +} +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.mt-1 { + margin-top: 0.25rem !important; +} +.mr-1 { + margin-right: 0.25rem !important; +} +.mb-1 { + margin-bottom: 0.25rem !important; +} +.ml-1 { + margin-left: 0.25rem !important; +} +.mx-1 { + margin-left: 0.25rem !important; + margin-right: 0.25rem !important; +} +.my-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; +} + +.mt-2 { + margin-top: 0.5rem !important; +} +.mr-2 { + margin-right: 0.5rem !important; +} +.mb-2 { + margin-bottom: 0.5rem !important; +} +.ml-2 { + margin-left: 0.5rem !important; +} +.mx-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; +} +.my-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; +} + +.mt-3 { + margin-top: 1rem !important; +} +.mr-3 { + margin-right: 1rem !important; +} +.mb-3 { + margin-bottom: 1rem !important; +} +.ml-3 { + margin-left: 1rem !important; +} +.mx-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; +} +.my-3 { + margin-bottom: 1rem !important; + margin-top: 1rem !important; +} + +.p-0 { + padding: 0 !important; +} +.p-1 { + padding: 0.25rem !important; +} +.p-2 { + padding: 0.5rem !important; +} +.p-3 { + padding: 1rem !important; +} +.p-4 { + padding: 1.5rem !important; +} +.p-5 { + padding: 3rem !important; +} + +.pt-0 { + padding-top: 0 !important; +} +.pr-0 { + padding-right: 0 !important; +} +.pb-0 { + padding-bottom: 0 !important; +} +.pl-0 { + padding-left: 0 !important; +} +.px-0 { + padding-left: 0 !important; + padding-right: 0 !important; +} +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.pt-1 { + padding-top: 0.25rem !important; +} +.pr-1 { + padding-right: 0.25rem !important; +} +.pb-1 { + padding-bottom: 0.25rem !important; +} +.pl-1 { + padding-left: 0.25rem !important; +} +.px-1 { + padding-left: 0.25rem !important; + padding-right: 0.25rem !important; +} +.py-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; +} + +.pt-2 { + padding-top: 0.5rem !important; +} +.pr-2 { + padding-right: 0.5rem !important; +} +.pb-2 { + padding-bottom: 0.5rem !important; +} +.pl-2 { + padding-left: 0.5rem !important; +} +.px-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; +} +.py-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; +} + +.pt-3 { + padding-top: 1rem !important; +} +.pr-3 { + padding-right: 1rem !important; +} +.pb-3 { + padding-bottom: 1rem !important; +} +.pl-3 { + padding-left: 1rem !important; +} +.px-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; +} +.py-3 { + padding-bottom: 1rem !important; + padding-top: 1rem !important; +} + +.password_background { + background-image: repeating-linear-gradient( + 45deg, + white 0%, + white 2%, + rgb(0, 0, 0) 2%, + rgb(0, 0, 0) 4%, + white 4% + ); +}