--- old/pkg/static/login.js +++ new/pkg/static/login.js @@ -225,7 +225,7 @@ css("display", "flex") && css("display", "grid") && css("selector(test)") && - css("selector(:is():where())"); + css("selector(:is(*):where(*))"); } function trim(s) { --- old/dist/static/login.js +++ new/dist/static/login.js @@ -1 +1 @@ -(()=>{"use strict";!function(t){let e,n;try{e=window.localStorage,window.localStorage.removeItem("url-root"),window.localStorage.removeItem("standard-login")}catch(n){e=window.sessionStorage,t.warn(String(n))}const o=window.environment||{},i=o.OAuth||null;i&&(i.TokenParam||(i.TokenParam="access_token"),i.ErrorParam||(i.ErrorParam="error_description"));const s=/\$\{([^}]+)\}|\$([a-zA-Z0-9_]+)/g;function r(t){const e=Array.prototype.slice.call(arguments,1);return t.replace(s,(function(t,n,o){return e[n||o]||""}))}function a(t){if(window.cockpit_po){const e=window.cockpit_po[t];if(e&&e[1])return e[1]}return t}const c=a;let l,d,u,p;const g=/[?&]?([^=]+)=([^&]*)/g;let f=null;function w(t){t=t.split("+").join(" ");const e={};for(;;){const n=g.exec(t);if(!n)break;e[decodeURIComponent(n[1])]=decodeURIComponent(n[2])}return e}function m(t){return document.getElementById(t)}function h(t,e){"string"==typeof t&&(t=[t]);for(let n=0;n2&&i[t-1]===i[0]&&(i=i.substr(1,t-2)),n.innerHTML=i||e}else n.removeAttribute("class")}function b(t){return t.replace(/^\s+|\s+$/g,"")}function C(t){const i=document.createElement("a");let s=document.baseURI;if(!s){const t=document.getElementsByTagName("base");s=t.length>0?t[0].href:"/"}t=t||"/",i.href=s,"/"!=i.pathname&&(n=i.pathname.replace(/^\/+|\/+$/g,""),e.setItem("url-root",n),n&&0===t.indexOf("/"+n)&&(t=t.replace("/"+n,"")||"/")),0===t.indexOf("/=")?(o.hostname=t.substring(2).split("/")[0],m("server-field").value=o.hostname,S(null,!0),t="/cockpit+"+t.split("/")[1]):0!==t.indexOf("/cockpit/")&&0!==t.indexOf("/cockpit+")&&(t="/cockpit"),d=t.split("/")[1],l="/"+d+"/login",n&&(l="/"+n+l),p=d,u=l}function S(t,e){t&&"keypress"===t.type&&" "!==t.key||(t&&"click"===t.type&&t.preventDefault(),void 0===e&&(e=m("server-group").hidden),h("#server-group",!e),m("option-group").setAttribute("data-state",e),e?(m("option-caret").classList.add("caret-down"),m("option-caret").classList.remove("caret-right")):(m("option-caret").classList.add("caret-right"),m("option-caret").classList.remove("caret-down")))}function L(t){const e=m("login-password-input");e.setAttribute("type","password"===e.getAttribute("type")?"text":"password"),t.stopPropagation()}function I(){const t=window.location.href.split("#",2);f=i.URL,i.URL.indexOf("?")>-1?f+="&":f+="?",f+="redirect_uri="+encodeURIComponent(t[0])}function T(){k("#error-group"),m("login-error-message").textContent=""}function E(){k("#info-group"),m("login-info-message").textContent=""}function O(t,e){T(),t&&(i?y(t):(N(e||"login"),m("login-error-message").textContent=t,v("#error-group")))}function _(t){m("server-field").value?(T(),m("login-error-message").textContent=t,v("#error-group"),S(null,!0),N("login")):O(t)}function A(){return o.page.require_host&&-1===p.indexOf("cockpit+=")}function R(){let n=[];try{n=JSON.parse(e.getItem("cockpit-client-sessions")||"[]")}catch(e){t.log("Failed to parse 'cockpit-client-sessions':",e)}return n}function U(){O(null);const t=b(m("login-user-input").value);if(""!==t||o.is_cockpit_client)if(A()&&""===m("server-field").value)O(c("Please specify the host to connect to"));else{const n=m("server-field").value;n?(d="cockpit+="+n,l=u.replace("/"+p+"/","/"+d+"/"),m("brand").style.display="none",m("badge").style.visibility="hidden"):(d=p,l=u,x("badge",""),x("brand","Cockpit")),m("server-name").textContent=n||o.hostname,m("login-button").removeEventListener("click",U);const i=m("login-password-input").value,s="superuser:"+t+(n?":"+n:""),r=e.getItem(s)||"none";e.setItem("superuser-key",s),e.setItem(s,r),e.setItem("standard-login",!0);const a={Authorization:"Basic "+window.btoa(J(t+":"+i)),"X-Superuser":r};n&&(a["X-SSH-Connect-Unknown-Hosts"]="yes"),M(0,a,!1)}else O(c("User name cannot be empty"))}function H(){const t=R(),n=m("recent-hosts-list");n.innerHTML="",t.forEach((o=>{const i=document.createElement("div");i.classList.add("host-line");const s=document.createElement("button");s.textContent=o,s.classList.add("pf-c-button","pf-m-tertiary","host-name"),s.addEventListener("click",(()=>{m("server-field").value=o,U()}));const r=document.createElement("button");r.title=c("Remove host"),r.ariaLabel=r.title,r.classList.add("pf-c-button","pf-m-tertiary","host-remove"),r.addEventListener("click",(()=>{const n=t.indexOf(o);t.splice(n,1),e.setItem("cockpit-client-sessions",JSON.stringify(t)),H()})),i.append(s,r),n.append(i)})),h("#recent-hosts",0==t.length)}function N(t){const e=o.page.connect;let n=m("option-group").getAttribute("data-state");if(k("#login-wait-validating"),v("#login"),h("#login-details",o.is_cockpit_client),h("#server-field-label",o.is_cockpit_client),o.is_cockpit_client){const t=m("brand");t.textContent=c("Connect to:"),t.classList.add("text-brand")}h(["#user-group","#password-group"],"login"!=t||o.is_cockpit_client),h("#conversation-group","conversation"!=t),h("#hostkey-group","hostkey"!=t),m("login-button-text").textContent=c("hostkey"==t?"Accept key and log in":"Log in"),m("login-password-input").value="",o.page.require_host?(k("#option-group"),n=!0):h("#option-group",!e||"login"!=t),e&&"login"==t?h("#server-group",!n):k("#server-group"),m("login-button").removeAttribute("disabled"),m("login-button").removeAttribute("spinning"),m("login-button").classList.remove("pf-m-danger"),m("login-button").classList.add("pf-m-primary"),k("#get-out-link"),"login"==t&&m("login-button").addEventListener("click",U),o.is_cockpit_client&&(H(),document.body.classList.add("cockpit-client"))}function P(t){var e;e=t,E(),e&&(m("login-info-message").textContent=e,v("#info-group")),m("server-name").textContent=document.title,function(t){const e=m("login-note");t?(v(e),e.textContent=t):e.innerHTML=" "}(c("Log in with your server user account.")),m("login-user-input").addEventListener("keydown",(function(t){O(null),E(),13==t.which&&m("login-password-input").focus()}),!1),m("login-password-input").addEventListener("keydown",(function(t){O(null),13==t.which&&U()})),m("login-password-toggle").addEventListener("click",L),N("login"),o.is_cockpit_client?o.page.require_host&&m("server-field").focus():m("login-user-input").focus()}function $(n){const o=function(){try{return JSON.parse(e.getItem("known_hosts")||"{ }")}catch(e){return t.warn("Can't parse known_hosts database in localStorage",e),{}}}(),i=n["host-key"],s=i.split(" ")[0],a=i.split(" ")[1];o[s]!=i?(o[s]?(m("hostkey-title").textContent=r(c("$0 key changed"),m("server-field").value),v("#hostkey-warning-group"),m("hostkey-message-1").textContent=""):(m("hostkey-title").textContent=c("New host"),k("#hostkey-warning-group"),m("hostkey-message-1").textContent=r(c("You are connecting to $0 for the first time."),m("server-field").value)),m("hostkey-verify-help-1").textContent=r(c("To verify a fingerprint, run the following on $0 while physically sitting at the machine or through a trusted network:"),m("server-field").value),m("hostkey-verify-help-cmds").textContent=r("ssh-keyscan$0 localhost | ssh-keygen -lf -",a?" -t "+a:""),m("hostkey-fingerprint").textContent=n.default,a?(m("hostkey-type").textContent=r("($0)",a),v("#hostkey-type")):k("#hostkey-type"),O(""),m("login-button").addEventListener("click",(function r(){m("login-button").removeEventListener("click",r),O(null,"hostkey"),o[s]=i,function(n){try{e.setItem("known_hosts",JSON.stringify(n))}catch(e){t.warn("Can't write known_hosts database to localStorage",e)}}(o),X(n.id,n.default)})),N("hostkey"),v("#get-out-link"),o[s]&&(m("login-button").classList.add("pf-m-danger"),m("login-button").classList.remove("pf-m-primary"))):X(n.id,n.default)}function q(t){if(t["host-key"])return void $(t);const e=t.echo?"text":"password";m("conversation-prompt").textContent=t.prompt;const n=m("conversation-message"),o=t.error||t.message;o?(n.textContent=o,v(n)):k(n);const i=m("conversation-input");function s(){m("conversation-input").removeEventListener("keydown",r),m("login-button").removeEventListener("click",s),O(null,"conversation"),X(t.id,m("conversation-input").value)}function r(t){O(null,"conversation"),13==t.which&&s()}i.value="",t.default&&(i.value=t.default),i.setAttribute("type",e),O(""),m("conversation-input").addEventListener("keydown",r),m("login-button").addEventListener("click",s),N("conversation"),i.focus()}function J(t){return window.unescape(encodeURIComponent(t))}function W(e,n){if(!e)return null;const o=e.split(" ");if("x-conversation"!==o[0].toLowerCase()&&3!=o.length)return null;const i=o[1];let s,r;try{s=window.atob(o[2])}catch(e){return window.console&&t.error("Invalid prompt data",e),null}try{r=JSON.parse(n)}catch(e){window.console&&t.log("Got invalid JSON response for prompt data",e),r={}}return r.id=i,r.prompt=s,r}function M(e,n,o){m("login-button").setAttribute("disabled","true"),m("login-button").setAttribute("spinning","true");const i=new XMLHttpRequest;i.open("GET",l,!0);for(const t in n)i.setRequestHeader(t,n[t]);i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status)B(JSON.parse(i.responseText));else if(401==i.status){const e=i.getResponseHeader("WWW-Authenticate");if(e&&0===e.toLowerCase().indexOf("x-conversation")){const t=W(e,i.responseText);t?q(t):y(c("Internal error: Invalid challenge header"))}else if(window.console&&t.log(i.statusText),i.statusText.startsWith("captured-stderr:"))!function(e){window.console&&t.warn("stderr:",e),k("#login-wait-validating"),k("#login","#login-details"),v("#login-fatal"),m("login-again").onclick=()=>{k("#login-fatal"),P()},v("#login-again");const n=m("login-fatal-message");n.textContent="",n.appendChild(document.createTextNode(e))}(decodeURIComponent(i.statusText.replace(/^captured-stderr:/,"")));else if(i.statusText.indexOf("authentication-not-supported")>-1){const t=b(m("login-user-input").value);y(r(c("The server refused to authenticate '$0' using password authentication, and no other supported authentication methods are available."),t))}else i.statusText.indexOf("terminated")>-1?O(c("Authentication failed: Server closed connection")):i.statusText.indexOf("no-host")>-1?_(c("Unable to connect to that address")):i.statusText.indexOf("unknown-hostkey")>-1?_(c("Refusing to connect. Hostkey is unknown")):i.statusText.indexOf("unknown-host")>-1?_(c("Refusing to connect. Host is unknown")):i.statusText.indexOf("invalid-hostkey")>-1?_(c("Refusing to connect. Hostkey does not match")):O(c(o?"Authentication failed":"Wrong user name or password"))}else 403==i.status?O(c(decodeURIComponent(i.statusText))||c("Permission denied")):i.statusText?y(decodeURIComponent(i.statusText)):y(r(c("$0 error"),i.status))},i.send()}function X(t,e){M(0,{Authorization:"X-Conversation "+t+" "+window.btoa(J(e))},!0)}function z(t,e,n){let o=0;for(;o{"use strict";!function(t){let e,n;try{e=window.localStorage,window.localStorage.removeItem("url-root"),window.localStorage.removeItem("standard-login")}catch(n){e=window.sessionStorage,t.warn(String(n))}const o=window.environment||{},i=o.OAuth||null;i&&(i.TokenParam||(i.TokenParam="access_token"),i.ErrorParam||(i.ErrorParam="error_description"));const s=/\$\{([^}]+)\}|\$([a-zA-Z0-9_]+)/g;function r(t){const e=Array.prototype.slice.call(arguments,1);return t.replace(s,(function(t,n,o){return e[n||o]||""}))}function a(t){if(window.cockpit_po){const e=window.cockpit_po[t];if(e&&e[1])return e[1]}return t}const c=a;let l,d,u,p;const g=/[?&]?([^=]+)=([^&]*)/g;let f=null;function w(t){t=t.split("+").join(" ");const e={};for(;;){const n=g.exec(t);if(!n)break;e[decodeURIComponent(n[1])]=decodeURIComponent(n[2])}return e}function m(t){return document.getElementById(t)}function h(t,e){"string"==typeof t&&(t=[t]);for(let n=0;n2&&i[t-1]===i[0]&&(i=i.substr(1,t-2)),n.innerHTML=i||e}else n.removeAttribute("class")}function b(t){return t.replace(/^\s+|\s+$/g,"")}function C(t){const i=document.createElement("a");let s=document.baseURI;if(!s){const t=document.getElementsByTagName("base");s=t.length>0?t[0].href:"/"}t=t||"/",i.href=s,"/"!=i.pathname&&(n=i.pathname.replace(/^\/+|\/+$/g,""),e.setItem("url-root",n),n&&0===t.indexOf("/"+n)&&(t=t.replace("/"+n,"")||"/")),0===t.indexOf("/=")?(o.hostname=t.substring(2).split("/")[0],m("server-field").value=o.hostname,S(null,!0),t="/cockpit+"+t.split("/")[1]):0!==t.indexOf("/cockpit/")&&0!==t.indexOf("/cockpit+")&&(t="/cockpit"),d=t.split("/")[1],l="/"+d+"/login",n&&(l="/"+n+l),p=d,u=l}function S(t,e){t&&"keypress"===t.type&&" "!==t.key||(t&&"click"===t.type&&t.preventDefault(),void 0===e&&(e=m("server-group").hidden),h("#server-group",!e),m("option-group").setAttribute("data-state",e),e?(m("option-caret").classList.add("caret-down"),m("option-caret").classList.remove("caret-right")):(m("option-caret").classList.add("caret-right"),m("option-caret").classList.remove("caret-down")))}function L(t){const e=m("login-password-input");e.setAttribute("type","password"===e.getAttribute("type")?"text":"password"),t.stopPropagation()}function I(){const t=window.location.href.split("#",2);f=i.URL,i.URL.indexOf("?")>-1?f+="&":f+="?",f+="redirect_uri="+encodeURIComponent(t[0])}function T(){k("#error-group"),m("login-error-message").textContent=""}function E(){k("#info-group"),m("login-info-message").textContent=""}function O(t,e){T(),t&&(i?y(t):(N(e||"login"),m("login-error-message").textContent=t,v("#error-group")))}function _(t){m("server-field").value?(T(),m("login-error-message").textContent=t,v("#error-group"),S(null,!0),N("login")):O(t)}function A(){return o.page.require_host&&-1===p.indexOf("cockpit+=")}function R(){let n=[];try{n=JSON.parse(e.getItem("cockpit-client-sessions")||"[]")}catch(e){t.log("Failed to parse 'cockpit-client-sessions':",e)}return n}function U(){O(null);const t=b(m("login-user-input").value);if(""!==t||o.is_cockpit_client)if(A()&&""===m("server-field").value)O(c("Please specify the host to connect to"));else{const n=m("server-field").value;n?(d="cockpit+="+n,l=u.replace("/"+p+"/","/"+d+"/"),m("brand").style.display="none",m("badge").style.visibility="hidden"):(d=p,l=u,x("badge",""),x("brand","Cockpit")),m("server-name").textContent=n||o.hostname,m("login-button").removeEventListener("click",U);const i=m("login-password-input").value,s="superuser:"+t+(n?":"+n:""),r=e.getItem(s)||"none";e.setItem("superuser-key",s),e.setItem(s,r),e.setItem("standard-login",!0);const a={Authorization:"Basic "+window.btoa(J(t+":"+i)),"X-Superuser":r};n&&(a["X-SSH-Connect-Unknown-Hosts"]="yes"),M(0,a,!1)}else O(c("User name cannot be empty"))}function H(){const t=R(),n=m("recent-hosts-list");n.innerHTML="",t.forEach((o=>{const i=document.createElement("div");i.classList.add("host-line");const s=document.createElement("button");s.textContent=o,s.classList.add("pf-c-button","pf-m-tertiary","host-name"),s.addEventListener("click",(()=>{m("server-field").value=o,U()}));const r=document.createElement("button");r.title=c("Remove host"),r.ariaLabel=r.title,r.classList.add("pf-c-button","pf-m-tertiary","host-remove"),r.addEventListener("click",(()=>{const n=t.indexOf(o);t.splice(n,1),e.setItem("cockpit-client-sessions",JSON.stringify(t)),H()})),i.append(s,r),n.append(i)})),h("#recent-hosts",0==t.length)}function N(t){const e=o.page.connect;let n=m("option-group").getAttribute("data-state");if(k("#login-wait-validating"),v("#login"),h("#login-details",o.is_cockpit_client),h("#server-field-label",o.is_cockpit_client),o.is_cockpit_client){const t=m("brand");t.textContent=c("Connect to:"),t.classList.add("text-brand")}h(["#user-group","#password-group"],"login"!=t||o.is_cockpit_client),h("#conversation-group","conversation"!=t),h("#hostkey-group","hostkey"!=t),m("login-button-text").textContent=c("hostkey"==t?"Accept key and log in":"Log in"),m("login-password-input").value="",o.page.require_host?(k("#option-group"),n=!0):h("#option-group",!e||"login"!=t),e&&"login"==t?h("#server-group",!n):k("#server-group"),m("login-button").removeAttribute("disabled"),m("login-button").removeAttribute("spinning"),m("login-button").classList.remove("pf-m-danger"),m("login-button").classList.add("pf-m-primary"),k("#get-out-link"),"login"==t&&m("login-button").addEventListener("click",U),o.is_cockpit_client&&(H(),document.body.classList.add("cockpit-client"))}function P(t){var e;e=t,E(),e&&(m("login-info-message").textContent=e,v("#info-group")),m("server-name").textContent=document.title,function(t){const e=m("login-note");t?(v(e),e.textContent=t):e.innerHTML=" "}(c("Log in with your server user account.")),m("login-user-input").addEventListener("keydown",(function(t){O(null),E(),13==t.which&&m("login-password-input").focus()}),!1),m("login-password-input").addEventListener("keydown",(function(t){O(null),13==t.which&&U()})),m("login-password-toggle").addEventListener("click",L),N("login"),o.is_cockpit_client?o.page.require_host&&m("server-field").focus():m("login-user-input").focus()}function $(n){const o=function(){try{return JSON.parse(e.getItem("known_hosts")||"{ }")}catch(e){return t.warn("Can't parse known_hosts database in localStorage",e),{}}}(),i=n["host-key"],s=i.split(" ")[0],a=i.split(" ")[1];o[s]!=i?(o[s]?(m("hostkey-title").textContent=r(c("$0 key changed"),m("server-field").value),v("#hostkey-warning-group"),m("hostkey-message-1").textContent=""):(m("hostkey-title").textContent=c("New host"),k("#hostkey-warning-group"),m("hostkey-message-1").textContent=r(c("You are connecting to $0 for the first time."),m("server-field").value)),m("hostkey-verify-help-1").textContent=r(c("To verify a fingerprint, run the following on $0 while physically sitting at the machine or through a trusted network:"),m("server-field").value),m("hostkey-verify-help-cmds").textContent=r("ssh-keyscan$0 localhost | ssh-keygen -lf -",a?" -t "+a:""),m("hostkey-fingerprint").textContent=n.default,a?(m("hostkey-type").textContent=r("($0)",a),v("#hostkey-type")):k("#hostkey-type"),O(""),m("login-button").addEventListener("click",(function r(){m("login-button").removeEventListener("click",r),O(null,"hostkey"),o[s]=i,function(n){try{e.setItem("known_hosts",JSON.stringify(n))}catch(e){t.warn("Can't write known_hosts database to localStorage",e)}}(o),X(n.id,n.default)})),N("hostkey"),v("#get-out-link"),o[s]&&(m("login-button").classList.add("pf-m-danger"),m("login-button").classList.remove("pf-m-primary"))):X(n.id,n.default)}function q(t){if(t["host-key"])return void $(t);const e=t.echo?"text":"password";m("conversation-prompt").textContent=t.prompt;const n=m("conversation-message"),o=t.error||t.message;o?(n.textContent=o,v(n)):k(n);const i=m("conversation-input");function s(){m("conversation-input").removeEventListener("keydown",r),m("login-button").removeEventListener("click",s),O(null,"conversation"),X(t.id,m("conversation-input").value)}function r(t){O(null,"conversation"),13==t.which&&s()}i.value="",t.default&&(i.value=t.default),i.setAttribute("type",e),O(""),m("conversation-input").addEventListener("keydown",r),m("login-button").addEventListener("click",s),N("conversation"),i.focus()}function J(t){return window.unescape(encodeURIComponent(t))}function W(e,n){if(!e)return null;const o=e.split(" ");if("x-conversation"!==o[0].toLowerCase()&&3!=o.length)return null;const i=o[1];let s,r;try{s=window.atob(o[2])}catch(e){return window.console&&t.error("Invalid prompt data",e),null}try{r=JSON.parse(n)}catch(e){window.console&&t.log("Got invalid JSON response for prompt data",e),r={}}return r.id=i,r.prompt=s,r}function M(e,n,o){m("login-button").setAttribute("disabled","true"),m("login-button").setAttribute("spinning","true");const i=new XMLHttpRequest;i.open("GET",l,!0);for(const t in n)i.setRequestHeader(t,n[t]);i.onreadystatechange=function(){if(4==i.readyState)if(200==i.status)B(JSON.parse(i.responseText));else if(401==i.status){const e=i.getResponseHeader("WWW-Authenticate");if(e&&0===e.toLowerCase().indexOf("x-conversation")){const t=W(e,i.responseText);t?q(t):y(c("Internal error: Invalid challenge header"))}else if(window.console&&t.log(i.statusText),i.statusText.startsWith("captured-stderr:"))!function(e){window.console&&t.warn("stderr:",e),k("#login-wait-validating"),k("#login","#login-details"),v("#login-fatal"),m("login-again").onclick=()=>{k("#login-fatal"),P()},v("#login-again");const n=m("login-fatal-message");n.textContent="",n.appendChild(document.createTextNode(e))}(decodeURIComponent(i.statusText.replace(/^captured-stderr:/,"")));else if(i.statusText.indexOf("authentication-not-supported")>-1){const t=b(m("login-user-input").value);y(r(c("The server refused to authenticate '$0' using password authentication, and no other supported authentication methods are available."),t))}else i.statusText.indexOf("terminated")>-1?O(c("Authentication failed: Server closed connection")):i.statusText.indexOf("no-host")>-1?_(c("Unable to connect to that address")):i.statusText.indexOf("unknown-hostkey")>-1?_(c("Refusing to connect. Hostkey is unknown")):i.statusText.indexOf("unknown-host")>-1?_(c("Refusing to connect. Host is unknown")):i.statusText.indexOf("invalid-hostkey")>-1?_(c("Refusing to connect. Hostkey does not match")):O(c(o?"Authentication failed":"Wrong user name or password"))}else 403==i.status?O(c(decodeURIComponent(i.statusText))||c("Permission denied")):i.statusText?y(decodeURIComponent(i.statusText)):y(r(c("$0 error"),i.status))},i.send()}function X(t,e){M(0,{Authorization:"X-Conversation "+t+" "+window.btoa(J(e))},!0)}function z(t,e,n){let o=0;for(;o