function fillTemplate(templateId, values) { var tpl = document.getElementById(templateId).text; Object.keys(values).forEach(key => { tpl = tpl.replace(new RegExp("\\[\\[ \\." + key + " \\]\\]", "g"), values[key]); }); var out = []; tpl.split("\n").forEach(line => { line = line.replace(/^\s+/, "").replace(/\s+$/, ""); if (line !== "") { out.push(line); } }); return out.join("\n"); } function getJSON(response) { if (!response.ok) { document.getElementById("api-error").style.display = "block"; throw new Error("Error loading api"); } return response.json(); } function accountTableLinkClick(event) { event.preventDefault(); var thisRow = event.target.parentElement.parentElement; var account = thisRow.dataset["accountName"]; var oldText = event.target.text; var existingTr = document.getElementById("credentials-for-" + account); if (existingTr) { existingTr.remove(); } event.target.text = "Loading..."; fetch(thisRow.dataset["globalCredentialEndpoint"], { "headers": { "Accept": event.target.dataset["contentType"] } }).then(r => r.text()).then(text => { var newTr = fillTemplate("credential_row_template", { "Account": account, "Content": text, }); event.target.text = oldText; thisRow.insertAdjacentHTML("afterend", newTr); thisRow.nextElementSibling.getElementsByTagName("button")[0].addEventListener("click", e => { e.target.parentNode.parentNode.remove(); }); }); return false; } function populateUserRow(row) { var [key, value] = row; var tokens = ""; if (value.is_admin) { tokens += 'Admin'; } if (value.is_service) { tokens += 'Service'; } var out = fillTemplate("user_row_template", { "username": key, "tokens": tokens, }); document.querySelector("#user-table tr").insertAdjacentHTML("afterend", out); } function populateAccountRow(row) { document.querySelector("#account-table tr").insertAdjacentHTML("afterend", fillTemplate(row["vendor"] + "_account_row_template", row)); document.querySelectorAll(".account-row a[data-content-type]").forEach(e => { e.addEventListener("click", accountTableLinkClick); }); } function getCookie(name) { return document.cookie.match(new RegExp(name + "=\"?([^;\"]*)\"?;?"))[1]; } function parseJWT() { return JSON.parse(atob(getCookie("github-token").split(".")[1])); } function parseJWTExpires() { return new Date(parseJWT()["exp"] * 1000); } function isAdmin() { return parseJWT()["admin"]; } function getApiUrl(formId) { var urlParts = window.location.pathname.split("/"); if (urlParts.length != 3) { return null; } var shortName = urlParts[urlParts.length-1]; return document.getElementById(formId).action + "/" + shortName; } function submitForm(target, url, method) { var result = {}; target.querySelectorAll("form input, form select").forEach(e => { if (e.selectedOptions !== undefined) { var items = []; Array.from(e.selectedOptions).forEach(i => items.push(i.value)); result[e.id] = items; } else if (e.type == "number") { result[e.id] = parseInt(e.value); } else { result[e.id] = e.value; } }); fetch(url, { "method": method, "headers": { "Content-Type": "application/vnd.broker.v2+json" }, "body": JSON.stringify(result) }) .then(r => { if (r.status < 299) { return { "request": r }; } else { return r.json().then(j => ({ "json": j, "request": r })) } }) .then(r => { if (r.request.status > 299) { document.getElementById("api-error").style.display = "block"; document.querySelector("#api-error .sub-message").innerText = r.json.message; } else { document.getElementById("api-success").style.display = "block"; } }) .catch(_ => document.getElementById("api-error").style.display = "block"); } function populateUsers(selected) { fetch("/api/user") .then(r => { if (r.status == 404) { return {}; } // If they can't load the user endpoint they will not be able to submt updates document.getElementById("submit-form").disabled = false; return r.json() }) .then(r => { var e = document.getElementById("users"); Object.entries(r).forEach(([key, value]) => { if (!selected[key]) { var opt = document.createElement("option"); opt.value = key; opt.innerText = key; e.appendChild(opt); } }); }) .catch(_ => document.getElementById("api-error").style.display = "block"); } function setupUserPage() { document.getElementById("back").addEventListener('click', _ => window.location.pathname = "/"); document.getElementById("user-form").addEventListener('submit', e => e.preventDefault()); var apiUrl = getApiUrl("user-form"); if (apiUrl == null) { document.getElementById("submit-form").addEventListener('click', e => { var target = document.getElementById("user-form"); submitForm(target, target.action, "POST"); e.preventDefault(); return false; }); } else { document.getElementById("submit-form").addEventListener('click', e => { var target = document.getElementById("user-form"); submitForm(target, getApiUrl(target.id), "PUT"); e.preventDefault(); return false; }); fetch(apiUrl) .then(r => r.json()) .then(r => { Object.entries(r).forEach(([key, value]) => { var e = document.getElementById(key); if (e === null) { return; } else if (e.type == "text") { e.value = value; } else if (e.type == "checkbox") { e.checked = value; } }); }) .catch(_ => document.getElementById("api-error").style.display = "block"); } } function setupManageAccount() { document.getElementById("submit-form").disabled = true; document.getElementById("back").addEventListener('click', _ => window.location.pathname = "/"); document.getElementById("account-form").addEventListener('submit', e => e.preventDefault()); var apiUrl = getApiUrl("account-form"); if (apiUrl == null) { populateUsers({}); document.getElementById("submit-form").addEventListener('click', e => { var target = document.getElementById("account-form"); submitForm(target, target.action, "POST"); e.preventDefault(); return false; }); } else { document.getElementById("submit-form").addEventListener('click', e => { var target = document.getElementById("account-form"); submitForm(target, getApiUrl(target.id), "PUT"); e.preventDefault(); return false; }); fetch(apiUrl) .then(r => r.json()) .then(r => { var selectedUsers = {}; Object.entries(r).forEach(([key, value]) => { var e = document.getElementById(key); if (e.type !== "select") { e.value = value; } if (key == "users") { value.forEach(v => { var opt = document.createElement("option"); opt.value = v; opt.selected = true; opt.innerText = v; e.appendChild(opt); selectedUsers[v] = true; }); } }); return selectedUsers; }) .then(populateUsers) .catch(_ => document.getElementById("api-error").style.display = "block"); } } function setupHomePage() { document.getElementById("add-account").addEventListener('click', _ => window.location.pathname = "/account"); document.getElementById("add-user").addEventListener('click', _ => window.location.pathname = "/user"); fetch("/api/account").then(getJSON).then(r => r.forEach(populateAccountRow)); document.getElementById("username").innerText = parseJWT()["sub"]; if (isAdmin()) { document.body.classList.add("isAdmin"); fetch("/api/user").then(getJSON).then(r => Object.entries(r).forEach(populateUserRow)); } document.getElementById("show-api-key").addEventListener("click", _ => { document.querySelector("#api-key textarea").innerText = getCookie("github-token"); document.querySelector("#session-expires").innerText = parseJWTExpires(); document.getElementById("api-key-block").style.display = "block"; }); }