diff --git a/relay/frontend/base.haml b/relay/frontend/base.haml index d7551b8..d3d8bb6 100644 --- a/relay/frontend/base.haml +++ b/relay/frontend/base.haml @@ -15,7 +15,7 @@ %link(rel="stylesheet" type="text/css" href="/static/style.css?{{version}}" nonce="{{view.request['hash']}}") %link(rel="stylesheet" type="text/css" href="/static/bootstrap-icons.css?{{version}}" nonce="{{view.request['hash']}}") %link(rel="manifest" href="/manifest.json?{{version}}") - %script(type="application/javascript" src="/static/api.js?{{version}}" nonce="{{view.request['hash']}}" defer) + %script(type="application/javascript" src="/static/functions.js?{{version}}" nonce="{{view.request['hash']}}" defer) -block head %body diff --git a/relay/frontend/page/admin-config.haml b/relay/frontend/page/admin-config.haml index 8dc0ad9..226c052 100644 --- a/relay/frontend/page/admin-config.haml +++ b/relay/frontend/page/admin-config.haml @@ -1,10 +1,7 @@ -extends "base.haml" -set page="Config" - --block head - %script(type="application/javascript" src="/static/config.js?{{version}}" nonce="{{view.request['hash']}}" defer) - -import "functions.haml" as func + -block content %fieldset.section %legend << Config diff --git a/relay/frontend/page/admin-domain_bans.haml b/relay/frontend/page/admin-domain_bans.haml index 66cec3d..8aa6728 100644 --- a/relay/frontend/page/admin-domain_bans.haml +++ b/relay/frontend/page/admin-domain_bans.haml @@ -1,9 +1,6 @@ -extends "base.haml" -set page="Domain Bans" --block head - %script(type="application/javascript" src="/static/domain_ban.js?{{version}}" nonce="{{view.request['hash']}}" defer) - -block content %details.section %summary << Ban Domain diff --git a/relay/frontend/page/admin-instances.haml b/relay/frontend/page/admin-instances.haml index 1490fdd..61e08a0 100644 --- a/relay/frontend/page/admin-instances.haml +++ b/relay/frontend/page/admin-instances.haml @@ -1,9 +1,6 @@ -extends "base.haml" -set page="Instances" --block head - %script(type="application/javascript" src="/static/instance.js?{{version}}" nonce="{{view.request['hash']}}" defer) - -block content %details.section %summary << Add Instance diff --git a/relay/frontend/page/admin-software_bans.haml b/relay/frontend/page/admin-software_bans.haml index 3bc4648..faaa57e 100644 --- a/relay/frontend/page/admin-software_bans.haml +++ b/relay/frontend/page/admin-software_bans.haml @@ -1,9 +1,6 @@ -extends "base.haml" -set page="Software Bans" --block head - %script(type="application/javascript" src="/static/software_ban.js?{{version}}" nonce="{{view.request['hash']}}" defer) - -block content %details.section %summary << Ban Software diff --git a/relay/frontend/page/admin-users.haml b/relay/frontend/page/admin-users.haml index caa9dc2..d6715c9 100644 --- a/relay/frontend/page/admin-users.haml +++ b/relay/frontend/page/admin-users.haml @@ -1,9 +1,6 @@ -extends "base.haml" -set page="Users" --block head - %script(type="application/javascript" src="/static/user.js?{{version}}" nonce="{{view.request['hash']}}" defer) - -block content %details.section %summary << Add User diff --git a/relay/frontend/page/admin-whitelist.haml b/relay/frontend/page/admin-whitelist.haml index 0a300dd..2fa3b99 100644 --- a/relay/frontend/page/admin-whitelist.haml +++ b/relay/frontend/page/admin-whitelist.haml @@ -1,9 +1,6 @@ -extends "base.haml" -set page="Whitelist" --block head - %script(type="application/javascript" src="/static/whitelist.js?{{version}}" nonce="{{view.request['hash']}}" defer) - -block content %details.section %summary << Add Domain diff --git a/relay/frontend/page/home.haml b/relay/frontend/page/home.haml index fa883d6..7db7551 100644 --- a/relay/frontend/page/home.haml +++ b/relay/frontend/page/home.haml @@ -1,5 +1,6 @@ -extends "base.haml" -set page = "Home" + -block content -if config.note .section diff --git a/relay/frontend/page/login.haml b/relay/frontend/page/login.haml index a56973a..c32160f 100644 --- a/relay/frontend/page/login.haml +++ b/relay/frontend/page/login.haml @@ -1,9 +1,6 @@ -extends "base.haml" -set page="Login" --block head - %script(type="application/javascript" src="/static/login.js?{{version}}" nonce="{{view.request['hash']}}" defer) - -block content %fieldset.section %legend << Login diff --git a/relay/frontend/static/api.js b/relay/frontend/static/api.js deleted file mode 100644 index 6aaefd7..0000000 --- a/relay/frontend/static/api.js +++ /dev/null @@ -1,131 +0,0 @@ -// toast notifications - -const notifications = document.querySelector("#notifications") - - -function remove_toast(toast) { - toast.classList.add("hide"); - - if (toast.timeoutId) { - clearTimeout(toast.timeoutId); - } - - setTimeout(() => toast.remove(), 300); -} - -function toast(text, type="error", timeout=5) { - const toast = document.createElement("li"); - toast.className = `section ${type}` - toast.innerHTML = `${text}✖` - - toast.querySelector("a").addEventListener("click", async (event) => { - event.preventDefault(); - await remove_toast(toast); - }); - - notifications.appendChild(toast); - toast.timeoutId = setTimeout(() => remove_toast(toast), timeout * 1000); -} - - -// menu - -const body = document.getElementById("container") -const menu = document.getElementById("menu"); -const menu_open = document.querySelector("#menu-open i"); -const menu_close = document.getElementById("menu-close"); - - -function toggle_menu() { - let new_value = menu.attributes.visible.nodeValue === "true" ? "false" : "true"; - menu.attributes.visible.nodeValue = new_value; -} - - -menu_open.addEventListener("click", toggle_menu); -menu_close.addEventListener("click", toggle_menu); - -body.addEventListener("click", (event) => { - if (event.target === menu_open) { - return; - } - - menu.attributes.visible.nodeValue = "false"; -}); - -for (const elem of document.querySelectorAll("#menu-open div")) { - elem.addEventListener("click", toggle_menu); -} - - -// misc - -function get_date_string(date) { - var year = date.getUTCFullYear().toString(); - var month = (date.getUTCMonth() + 1).toString().padStart(2, "0"); - var day = date.getUTCDate().toString().padStart(2, "0"); - - return `${year}-${month}-${day}`; -} - - -function append_table_row(table, row_name, row) { - var table_row = table.insertRow(-1); - table_row.id = row_name; - - index = 0; - - for (var prop in row) { - if (Object.prototype.hasOwnProperty.call(row, prop)) { - var cell = table_row.insertCell(index); - cell.className = prop; - cell.innerHTML = row[prop]; - - index += 1; - } - } - - return table_row; -} - - -async function request(method, path, body = null) { - var headers = { - "Accept": "application/json" - } - - if (body !== null) { - headers["Content-Type"] = "application/json" - body = JSON.stringify(body) - } - - const response = await fetch("/api/" + path, { - method: method, - mode: "cors", - cache: "no-store", - redirect: "follow", - body: body, - headers: headers - }); - - const message = await response.json(); - - if (Object.hasOwn(message, "error")) { - throw new Error(message.error); - } - - if (Array.isArray(message)) { - message.forEach((msg) => { - if (Object.hasOwn(msg, "created")) { - msg.created = new Date(msg.created); - } - }); - - } else { - if (Object.hasOwn(message, "created")) { - message.created = new Date(message.created); - } - } - - return message; -} diff --git a/relay/frontend/static/config.js b/relay/frontend/static/config.js deleted file mode 100644 index 612f4f3..0000000 --- a/relay/frontend/static/config.js +++ /dev/null @@ -1,52 +0,0 @@ -const elems = [ - document.querySelector("#name"), - document.querySelector("#note"), - document.querySelector("#theme"), - document.querySelector("#log-level"), - document.querySelector("#whitelist-enabled"), - document.querySelector("#approval-required") -] - - -async function handle_config_change(event) { - params = { - key: event.target.id, - value: event.target.type === "checkbox" ? event.target.checked : event.target.value - } - - try { - await request("POST", "v1/config", params); - - } catch (error) { - toast(error); - return; - } - - if (params.key === "name") { - document.querySelector("#header .title").innerHTML = params.value; - document.querySelector("title").innerHTML = params.value; - } - - if (params.key === "theme") { - document.querySelector("link.theme").href = `/theme/${params.value}.css`; - } - - toast("Updated config", "message"); -} - - -document.querySelector("#name").addEventListener("keydown", async (event) => { - if (event.which === 13) { - await handle_config_change(event); - } -}); - -document.querySelector("#note").addEventListener("keydown", async (event) => { - if (event.which === 13 && event.ctrlKey) { - await handle_config_change(event); - } -}); - -for (const elem of elems) { - elem.addEventListener("change", handle_config_change); -} diff --git a/relay/frontend/static/domain_ban.js b/relay/frontend/static/domain_ban.js deleted file mode 100644 index cdffbd3..0000000 --- a/relay/frontend/static/domain_ban.js +++ /dev/null @@ -1,131 +0,0 @@ -function create_ban_object(domain, reason, note) { - var text = '
\n'; - text += `${domain}\n`; - text += '
\n'; - text += `\n`; - text += `\n`; - text += `\n`; - text += `\n`; - text += ``; - text += '
'; - - return text; -} - - -function add_row_listeners(row) { - row.querySelector(".update-ban").addEventListener("click", async (event) => { - await update_ban(row.id); - }); - - row.querySelector(".remove a").addEventListener("click", async (event) => { - event.preventDefault(); - await unban(row.id); - }); -} - - -async function ban() { - var table = document.querySelector("table"); - var elems = { - domain: document.getElementById("new-domain"), - reason: document.getElementById("new-reason"), - note: document.getElementById("new-note") - } - - var values = { - domain: elems.domain.value.trim(), - reason: elems.reason.value.trim(), - note: elems.note.value.trim() - } - - if (values.domain === "") { - toast("Domain is required"); - return; - } - - try { - var ban = await request("POST", "v1/domain_ban", values); - - } catch (err) { - toast(err); - return - } - - var row = append_table_row(document.querySelector("table"), ban.domain, { - domain: create_ban_object(ban.domain, ban.reason, ban.note), - date: get_date_string(ban.created), - remove: `
` - }); - - add_row_listeners(row); - - elems.domain.value = null; - elems.reason.value = null; - elems.note.value = null; - - document.querySelector("details.section").open = false; - toast("Banned domain", "message"); -} - - -async function update_ban(domain) { - var row = document.getElementById(domain); - - var elems = { - "reason": row.querySelector("textarea.reason"), - "note": row.querySelector("textarea.note") - } - - var values = { - "domain": domain, - "reason": elems.reason.value, - "note": elems.note.value - } - - try { - await request("PATCH", "v1/domain_ban", values) - - } catch (error) { - toast(error); - return; - } - - row.querySelector("details").open = false; - toast("Updated baned domain", "message"); -} - - -async function unban(domain) { - try { - await request("DELETE", "v1/domain_ban", {"domain": domain}); - - } catch (error) { - toast(error); - return; - } - - document.getElementById(domain).remove(); - toast("Unbanned domain", "message"); -} - - -document.querySelector("#new-ban").addEventListener("click", async (event) => { - await ban(); -}); - -for (var elem of document.querySelectorAll("#add-item input")) { - elem.addEventListener("keydown", async (event) => { - if (event.which === 13) { - await ban(); - } - }); -} - -for (var row of document.querySelector("fieldset.section table").rows) { - if (!row.querySelector(".update-ban")) { - continue; - } - - add_row_listeners(row); -} diff --git a/relay/frontend/static/instance.js b/relay/frontend/static/instance.js deleted file mode 100644 index 9519ebc..0000000 --- a/relay/frontend/static/instance.js +++ /dev/null @@ -1,153 +0,0 @@ -function add_instance_listeners(row) { - row.querySelector(".remove a").addEventListener("click", async (event) => { - event.preventDefault(); - await del_instance(row.id); - }); -} - - -function add_request_listeners(row) { - row.querySelector(".approve a").addEventListener("click", async (event) => { - event.preventDefault(); - await req_response(row.id, true); - }); - - row.querySelector(".deny a").addEventListener("click", async (event) => { - event.preventDefault(); - await req_response(row.id, false); - }); -} - - -async function add_instance() { - var elems = { - actor: document.getElementById("new-actor"), - inbox: document.getElementById("new-inbox"), - followid: document.getElementById("new-followid"), - software: document.getElementById("new-software") - } - - var values = { - actor: elems.actor.value.trim(), - inbox: elems.inbox.value.trim(), - followid: elems.followid.value.trim(), - software: elems.software.value.trim() - } - - if (values.actor === "") { - toast("Actor is required"); - return; - } - - try { - var instance = await request("POST", "v1/instance", values); - - } catch (err) { - toast(err); - return - } - - row = append_table_row(document.getElementById("instances"), instance.domain, { - domain: `${instance.domain}`, - software: instance.software, - date: get_date_string(instance.created), - remove: `` - }); - - add_instance_listeners(row); - - elems.actor.value = null; - elems.inbox.value = null; - elems.followid.value = null; - elems.software.value = null; - - document.querySelector("details.section").open = false; - toast("Added instance", "message"); -} - - -async function del_instance(domain) { - try { - await request("DELETE", "v1/instance", {"domain": domain}); - - } catch (error) { - toast(error); - return; - } - - document.getElementById(domain).remove(); -} - - -async function req_response(domain, accept) { - params = { - "domain": domain, - "accept": accept - } - - try { - await request("POST", "v1/request", params); - - } catch (error) { - toast(error); - return; - } - - document.getElementById(domain).remove(); - - if (document.getElementById("requests").rows.length < 2) { - document.querySelector("fieldset.requests").remove() - } - - if (!accept) { - toast("Denied instance request", "message"); - return; - } - - instances = await request("GET", `v1/instance`, null); - instances.forEach((instance) => { - if (instance.domain === domain) { - row = append_table_row(document.getElementById("instances"), instance.domain, { - domain: `${instance.domain}`, - software: instance.software, - date: get_date_string(instance.created), - remove: `` - }); - - add_instance_listeners(row); - } - }); - - toast("Accepted instance request", "message"); -} - - -document.querySelector("#add-instance").addEventListener("click", async (event) => { - await add_instance(); -}) - -for (var elem of document.querySelectorAll("#add-item input")) { - elem.addEventListener("keydown", async (event) => { - if (event.which === 13) { - await add_instance(); - } - }); -} - -for (var row of document.querySelector("#instances").rows) { - if (!row.querySelector(".remove a")) { - continue; - } - - add_instance_listeners(row); -} - -if (document.querySelector("#requests")) { - for (var row of document.querySelector("#requests").rows) { - if (!row.querySelector(".approve a")) { - continue; - } - - add_request_listeners(row); - } -} diff --git a/relay/frontend/static/login.js b/relay/frontend/static/login.js deleted file mode 100644 index c61a7f4..0000000 --- a/relay/frontend/static/login.js +++ /dev/null @@ -1,42 +0,0 @@ -const fields = { - username: document.querySelector("#username"), - password: document.querySelector("#password") -} - -async function login(event) { - const values = { - username: fields.username.value.trim(), - password: fields.password.value.trim() - } - - if (values.username === "" | values.password === "") { - toast("Username and/or password field is blank"); - return; - } - - try { - await request("POST", "v1/token", values); - - } catch (error) { - toast(error); - return; - } - - document.location = "/"; -} - - -document.querySelector("#username").addEventListener("keydown", async (event) => { - if (event.which === 13) { - fields.password.focus(); - fields.password.select(); - } -}); - -document.querySelector("#password").addEventListener("keydown", async (event) => { - if (event.which === 13) { - await login(event); - } -}); - -document.querySelector(".submit").addEventListener("click", login); diff --git a/relay/frontend/static/software_ban.js b/relay/frontend/static/software_ban.js deleted file mode 100644 index bb54dbe..0000000 --- a/relay/frontend/static/software_ban.js +++ /dev/null @@ -1,138 +0,0 @@ -function create_ban_object(name, reason, note) { - var text = '
\n'; - text += `${name}\n`; - text += '
\n'; - text += `\n`; - text += `\n`; - text += `\n`; - text += `\n`; - text += ``; - text += '
'; - - return text; -} - - -function add_row_listeners(row) { - row.querySelector(".update-ban").addEventListener("click", async (event) => { - await update_ban(row.id); - }); - - row.querySelector(".remove a").addEventListener("click", async (event) => { - event.preventDefault(); - await unban(row.id); - }); -} - - -async function ban() { - var elems = { - name: document.getElementById("new-name"), - reason: document.getElementById("new-reason"), - note: document.getElementById("new-note") - } - - var values = { - name: elems.name.value.trim(), - reason: elems.reason.value, - note: elems.note.value - } - - if (values.name === "") { - toast("Domain is required"); - return; - } - - try { - var ban = await request("POST", "v1/software_ban", values); - - } catch (err) { - toast(err); - return - } - - var row = append_table_row(document.getElementById("bans"), ban.name, { - name: create_ban_object(ban.name, ban.reason, ban.note), - date: get_date_string(ban.created), - remove: `` - }); - - add_row_listeners(row); - - elems.name.value = null; - elems.reason.value = null; - elems.note.value = null; - - document.querySelector("details.section").open = false; - toast("Banned software", "message"); -} - - -async function update_ban(name) { - var row = document.getElementById(name); - - var elems = { - "reason": row.querySelector("textarea.reason"), - "note": row.querySelector("textarea.note") - } - - var values = { - "name": name, - "reason": elems.reason.value, - "note": elems.note.value - } - - try { - await request("PATCH", "v1/software_ban", values) - - } catch (error) { - toast(error); - return; - } - - row.querySelector("details").open = false; - toast("Updated software ban", "message"); -} - - -async function unban(name) { - try { - await request("DELETE", "v1/software_ban", {"name": name}); - - } catch (error) { - toast(error); - return; - } - - document.getElementById(name).remove(); - toast("Unbanned software", "message"); -} - - -document.querySelector("#new-ban").addEventListener("click", async (event) => { - await ban(); -}); - -for (var elem of document.querySelectorAll("#add-item input")) { - elem.addEventListener("keydown", async (event) => { - if (event.which === 13) { - await ban(); - } - }); -} - -for (var elem of document.querySelectorAll("#add-item textarea")) { - elem.addEventListener("keydown", async (event) => { - if (event.which === 13 && event.ctrlKey) { - await ban(); - } - }); -} - -for (var row of document.querySelector("#bans").rows) { - if (!row.querySelector(".update-ban")) { - continue; - } - - add_row_listeners(row); -} diff --git a/relay/frontend/static/user.js b/relay/frontend/static/user.js deleted file mode 100644 index 5bc16ec..0000000 --- a/relay/frontend/static/user.js +++ /dev/null @@ -1,93 +0,0 @@ -function add_row_listeners(row) { - row.querySelector(".remove a").addEventListener("click", async (event) => { - event.preventDefault(); - await del_user(row.id); - }); -} - - -async function add_user() { - var elems = { - username: document.getElementById("new-username"), - password: document.getElementById("new-password"), - password2: document.getElementById("new-password2"), - handle: document.getElementById("new-handle") - } - - var values = { - username: elems.username.value.trim(), - password: elems.password.value.trim(), - password2: elems.password2.value.trim(), - handle: elems.handle.value.trim() - } - - if (values.username === "" | values.password === "" | values.password2 === "") { - toast("Username, password, and password2 are required"); - return; - } - - if (values.password !== values.password2) { - toast("Passwords do not match"); - return; - } - - try { - var user = await request("POST", "v1/user", values); - - } catch (err) { - toast(err); - return - } - - var row = append_table_row(document.querySelector("fieldset.section table"), user.username, { - domain: user.username, - handle: user.handle ? self.handle : "n/a", - date: get_date_string(user.created), - remove: `` - }); - - add_row_listeners(row); - - elems.username.value = null; - elems.password.value = null; - elems.password2.value = null; - elems.handle.value = null; - - document.querySelector("details.section").open = false; - toast("Created user", "message"); -} - - -async function del_user(username) { - try { - await request("DELETE", "v1/user", {"username": username}); - - } catch (error) { - toast(error); - return; - } - - document.getElementById(username).remove(); - toast("Deleted user", "message"); -} - - -document.querySelector("#new-user").addEventListener("click", async (event) => { - await add_user(); -}); - -for (var elem of document.querySelectorAll("#add-item input")) { - elem.addEventListener("keydown", async (event) => { - if (event.which === 13) { - await add_user(); - } - }); -} - -for (var row of document.querySelector("#users").rows) { - if (!row.querySelector(".remove a")) { - continue; - } - - add_row_listeners(row); -} diff --git a/relay/frontend/static/whitelist.js b/relay/frontend/static/whitelist.js deleted file mode 100644 index c2b31e4..0000000 --- a/relay/frontend/static/whitelist.js +++ /dev/null @@ -1,70 +0,0 @@ -function add_row_listeners(row) { - row.querySelector(".remove a").addEventListener("click", async (event) => { - event.preventDefault(); - await del_whitelist(row.id); - }); -} - - -async function add_whitelist() { - var domain_elem = document.getElementById("new-domain"); - var domain = domain_elem.value.trim(); - - if (domain === "") { - toast("Domain is required"); - return; - } - - try { - var item = await request("POST", "v1/whitelist", {"domain": domain}); - - } catch (err) { - toast(err); - return; - } - - var row = append_table_row(document.getElementById("whitelist"), item.domain, { - domain: item.domain, - date: get_date_string(item.created), - remove: `` - }); - - add_row_listeners(row); - - domain_elem.value = null; - document.querySelector("details.section").open = false; - toast("Added domain", "message"); -} - - -async function del_whitelist(domain) { - try { - await request("DELETE", "v1/whitelist", {"domain": domain}); - - } catch (error) { - toast(error); - return; - } - - document.getElementById(domain).remove(); - toast("Removed domain", "message"); -} - - -document.querySelector("#new-item").addEventListener("click", async (event) => { - await add_whitelist(); -}); - -document.querySelector("#add-item").addEventListener("keydown", async (event) => { - if (event.which === 13) { - await add_whitelist(); - } -}); - -for (var row of document.querySelector("fieldset.section table").rows) { - if (!row.querySelector(".remove a")) { - continue; - } - - add_row_listeners(row); -}