// polyfills for older browsers if (typeof String.prototype.startsWith === 'undefined') { String.prototype.startsWith = function (needle) { return this.indexOf(needle) === 0; }; } // === Core functions === var api_base = "http://localhost:5000"; var app_token = null; var app_key_id = null; function do_request(method, url, data, onsuccess, onerror) { var req = new XMLHttpRequest(); req.open(method, window.encodeURI(api_base + url), true); req.onload = function() { onsuccess(this); } req.setRequestHeader("X-Auth-Token", app_token); req.onerror = function() { onerror(this); } if (data === null) { req.send(); } else { req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); req.send(data); } } // == Events === function oninit() { ui_keyholder_loading(); if (window.location.href.search("#tracker") < 0 && window.location.href.search("#keyholder") < 0) window.location.href = "#tracker" app_token = _get_token(); app_key_id = _get_key_id(app_token); if (app_token === null || app_key_id === null) { ui_tracker_error("Interner Fehler: kein/ungültiges Token. Bitte stelle sicher, dass du diese Seite durch Scannen des QR Codes erreicht hast"); return; } if (window.location.href.search("#keyholder") > 0) keyholder_onload(); update_key_name(); update_key_status(); load_saved_tracker_data(); document.getElementById("input-contact").addEventListener("keyup", function(e) { if (e.key === "Enter") tracker_onsend(); }); document.getElementById("input-pass").addEventListener("keyup", function(e) { if (e.key === "Enter") password_submit(); }); } function tracker_onsend(e) { ui_tracker_error(false); var name = document.getElementById("input-name").value; var contact = document.getElementById("input-contact").value; var save_data = document.getElementById("input-tracker-save").checked; if (name.length < 2 || contact.length < 2) { ui_tracker_error("Name und Kontakt müssen mindestens 3 Zeichen lang sein") return; } if (app_token === null) { ui_tracker_error("Interner Fehler: kein Token. Bitte stelle sicher, dass du diese Seite durch Scannen des QR Codes erreicht hast"); return; } ui_tracker_send_loading(true); do_request( "POST", "/claim", "name="+window.encodeURI(name)+"&contact="+window.encodeURI(contact), function(r) { ui_tracker_send_loading(true); if (r.status == 200) { localStorage.setItem(app_key_id + "_last_cid", r.response); if (save_data) { localStorage.setItem("name", name); localStorage.setItem("contact", contact); } else { localStorage.removeItem("name"); localStorage.removeItem("contact"); } update_key_status(); } else { ui_tracker_error("Fehlgeschlagen: Status code " + r.status); console.log("Claim request failed (Status code)"); console.log(r); } }, function(r) { ui_tracker_send_loading(true); ui_tracker_error("Fehlgeschlagen: Bitte überprüfe deine Internetverbindung"); console.log("Claim request failed"); console.log(r); } ); } function keyholder_onload() { ui_password_error(false); ui_keyholder_error(false); ui_keyholder_refresh_loading(true); do_request( "GET", "/keyholder", null, function(r) { ui_keyholder_refresh_loading(false); if (r.status == 200) { ui_show_keyholder(JSON.parse(r.response)); } else if (r.status == 403) { ui_request_password(); } else { ui_keyholder_error("Fehlgeschlagen: Status code " + r.status); console.log("Keyholder request failed (Status code)"); console.log(r); } }, function(r) { ui_keyholder_refresh_loading(false); ui_keyholder_error("Fehlgeschlagen: Bitte überprüfe deine Internetverbindung"); console.log("Keyholder request failed"); console.log(r); }, ); } function password_submit() { ui_password_error(false); ui_keyholder_error(false); var pass = document.getElementById("input-pass").value; var save_token = document.getElementById("input-pass-save").checked; document.getElementById("btn-send-pw").classList.add("loading"); do_request( "POST", "/auth", "pass=" + window.encodeURI(pass), function(r) { document.getElementById("btn-send-pw").classList.remove("loading"); if (r.status == 200) { // Delete previously used token if (app_token !== null && localStorage.getItem("token") !== null) { var tokenlist = localStorage.getItem("token").split(","); if (tokenlist.indexOf(app_token) !== -1) { tokenlist.splice(tokenlist.indexOf(app_token), 1); localStorage.setItem("token", tokenlist.join(",")); } } app_token = r.response; if (save_token) { if (localStorage.getItem("token") !== null) localStorage.setItem("token", localStorage.getItem("token") + "," + app_token); else localStorage.setItem("token", app_token) } ui_keyholder_loading(); keyholder_onload(); } else if (r.status == 401) { ui_password_error(true); } else { ui_keyholder_error("Fehlgeschlagen: Status code " + r.status); console.log("Auth request failed (Status code)"); console.log(r); } }, function(r) { document.getElementById("btn-send-pw").classList.remove("loading"); ui_keyholder_error("Fehlgeschlagen: Bitte überprüfe deine Internetverbindung"); console.log("Auth request failed"); console.log(r); } ); } // === Helper functions === function update_key_status() { var last_cid = localStorage.getItem(app_key_id + "_last_cid"); if (last_cid !== null) { do_request( "GET", "/status/" + last_cid, null, function(r) { if (r.status == 200 && r.response == "latest") ui_set_has_key(); else ui_set_has_not_key(); }, function(r) { console.log("Status request failed"); console.log(r) } ); } } function update_key_name() { // For perception purposes, the last key name is cached but // updated as soon as possible. var last_key_name = localStorage.getItem(app_key_id + "_last_key_name"); if (last_key_name !== null) ui_set_key_name(last_key_name); do_request( "GET", "/keyname", null, function(r) { if (r.status == 200) { ui_set_key_name(r.response); localStorage.setItem(app_key_id + "_last_key_name", r.response); } else { ui_set_key_name("?"); console.log("Keyname request failed (status code " + r.status + ")"); } }, function(r) { ui_set_key_name("?"); console.log("Keyname request failed"); console.log(r) } ); } function load_saved_tracker_data() { if (localStorage.getItem("name") !== null) document.getElementById("input-name").value = localStorage.getItem("name"); if (localStorage.getItem("contact") !== null) document.getElementById("input-contact").value = localStorage.getItem("contact"); } function _get_token() { // A token in the URL is always required to know the key var token = null; // Very dirty parsing as of now var params_str = window.location.search; if (params_str.search("&") >= 0) return null; var parts = params_str.split("token="); if (parts.length != 2) return null else token = parts[1]; if (localStorage.getItem("token") === null) { return token; } else { var key_id = token.split(":")[0]; var tokenlist = localStorage.getItem("token").split(","); // This returns the last stored token for this key. // Generally it should not happen (tm) that there is more than one token. for (var i = tokenlist.length - 1; i >= 0; i--) { if (tokenlist[i].indexOf(key_id + ":") === 0) return tokenlist[i]; } return token; } } function _get_key_id(token) { if (token === null) { return null; } else { var parts = token.split(":"); if (parts.length !== 2) return null else return parts[0]; } } // === Ugly UI manipulation code === function ui_set_has_key() { document.getElementById("has-key").style.display = "inline" document.getElementById("btn-tracker").disabled = true document.getElementById("input-name").disabled = true document.getElementById("input-contact").disabled = true document.getElementById("input-tracker-save").disabled = true document.getElementById("tracker-formgroup").style.opacity = 0.5 } function ui_set_has_not_key() { document.getElementById("has-key").style.display = "none" document.getElementById("btn-tracker").disabled = false document.getElementById("input-name").disabled = false document.getElementById("input-contact").disabled = false document.getElementById("input-tracker-save").disabled = false document.getElementById("tracker-formgroup").style.opacity = 1 } function ui_set_key_name(name) { document.getElementById("tracker-key-name").textContent = name; document.getElementById("keyholder-key-name").textContent = name; } function ui_keyholder_loading() { document.getElementById("keyholder-loading").style.display = "block" document.getElementById("btn-send-pw").style.display = "none" document.getElementById("btn-update").style.display = "none" document.getElementById("pass-formgroup").style.display = "none" document.getElementById("keyholder-table-container").style.display = "none" } function ui_request_password() { document.getElementById("keyholder-loading").style.display = "none" document.getElementById("btn-send-pw").style.display = "block" document.getElementById("btn-update").style.display = "none" document.getElementById("pass-formgroup").style.display = "block" document.getElementById("keyholder-table-container").style.display = "none" } function ui_show_keyholder(keyholder) { document.getElementById("keyholder-tbody").innerHTML = ""; for (var i = 0; i < keyholder.length; i++) { var date = new Date(keyholder[i]["timestamp"] * 1000); var tr = document.createElement("tr"); if (i > 0) tr.style.color = "#aaa"; var td_name = document.createElement("td"); var td_contact = document.createElement("td"); var td_timestamp = document.createElement("td"); td_name.appendChild(document.createTextNode(keyholder[i]["name"])); td_contact.appendChild(document.createTextNode(keyholder[i]["contact"])); td_timestamp.appendChild(document.createTextNode(date.toLocaleString())); tr.appendChild(td_name); tr.appendChild(td_contact); tr.appendChild(td_timestamp); document.getElementById("keyholder-tbody").appendChild(tr); } document.getElementById("keyholder-loading").style.display = "none" document.getElementById("btn-send-pw").style.display = "none" document.getElementById("btn-update").style.display = "block" document.getElementById("pass-formgroup").style.display = "none" document.getElementById("keyholder-table-container").style.display = "block" } function ui_keyholder_refresh_loading(is_loading) { if (is_loading) document.getElementById("btn-update").classList.add("loading"); else document.getElementById("btn-update").classList.remove("loading"); } function ui_tracker_send_loading(is_loading) { if (is_loading) document.getElementById("btn-tracker").classList.add("loading"); else document.getElementById("btn-tracker").classList.remove("loading"); } function ui_tracker_error(msg) { if (msg === false) { document.getElementById("tracker-error").style.display = "none"; } else { document.getElementById("tracker-error").innerHTML = msg; document.getElementById("tracker-error").style.display = "block"; } } function ui_keyholder_error(msg) { if (msg === false) { document.getElementById("keyholder-error").style.display = "none"; } else { document.getElementById("keyholder-error").innerHTML = msg; document.getElementById("keyholder-error").style.display = "block"; } } function ui_password_error(is_error) { if (is_error) document.getElementById("input-pass").classList.add("is-error"); else document.getElementById("input-pass").classList.remove("is-error"); }