\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);
+ }
+}
+
+
+function page_instance() {
+ 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);
+ }
+ }
+}
+
+
+function page_login() {
+ 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);
+}
+
+
+function page_software_ban() {
+ 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);
+ }
+}
+
+
+function page_user() {
+ 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);
+ }
+}
+
+
+function page_whitelist() {
+ 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);
+ }
+}
+
+
+if (location.pathname.startsWith("/admin/config")) {
+ page_config();
+
+} else if (location.pathname.startsWith("/admin/domain_bans")) {
+ page_domain_ban();
+
+} else if (location.pathname.startsWith("/admin/instances")) {
+ page_instance();
+
+} else if (location.pathname.startsWith("/admin/login")) {
+ page_login();
+
+} else if (location.pathname.startsWith("/admin/software_bans")) {
+ page_software_ban();
+
+} else if (location.pathname.startsWith("/admin/users")) {
+ page_user();
+
+} else if (location.pathname.startsWith("/admin/whitelist")) {
+ page_whitelist();
+}