From 299864ee0901df8db2314cc7c07d6c481927c8aa Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Thu, 13 Jan 2022 16:47:07 +0100 Subject: facilitate managing script blocking with a list of edtable entries --- html/payload_create.js | 17 ++---- html/text_entry_list.js | 134 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 129 insertions(+), 22 deletions(-) (limited to 'html') diff --git a/html/payload_create.js b/html/payload_create.js index c1563ae..503a461 100644 --- a/html/payload_create.js +++ b/html/payload_create.js @@ -46,7 +46,8 @@ #FROM html/DOM_helpers.js IMPORT clone_template #FROM common/sha256.js IMPORT sha256 -#FROM common/patterns.js IMPORT deconstruct_url, patterns_doc_url +#FROM common/patterns.js IMPORT validate_normalize_url_pattern, \ + patterns_doc_url /* https://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid */ /* This is a helper function used by uuidv4(). */ @@ -81,18 +82,8 @@ function collect_form_data(form_ctx) const payloads = {}; - for (const pattern of url_patterns) { - try { - deconstruct_url(pattern); - } catch(e) { - const patterns_doc_link = document.createElement("a"); - patterns_doc_link.href = patterns_doc_url; - patterns_doc_link.innerText = "here"; - const msg = document.createElement("span"); - msg.prepend(`'${pattern}' is not a valid URL pattern. See `, - patterns_doc_link, " for more details."); - throw msg; - } + for (let pattern of url_patterns) { + pattern = validate_normalize_url_pattern(pattern); if (pattern in payloads) throw `Pattern '${pattern}' specified multiple times!`; diff --git a/html/text_entry_list.js b/html/text_entry_list.js index 4af19fd..ff63c79 100644 --- a/html/text_entry_list.js +++ b/html/text_entry_list.js @@ -46,7 +46,7 @@ #IMPORT common/indexeddb.js AS haketilodb #FROM html/DOM_helpers.js IMPORT clone_template -#FROM common/patterns.js IMPORT deconstruct_url, patterns_doc_url +#FROM common/patterns.js IMPORT validate_normalize_url_pattern const coll = new Intl.Collator(); @@ -232,7 +232,7 @@ function TextEntryList(dialog_ctx, destroy_cb, async function repo_list(dialog_ctx) { let list; - function validate_normalize_repo_url(repo_url) { + function validate_normalize(repo_url) { let error_msg; /* In the future we might also try making a test connection. */ @@ -251,30 +251,32 @@ async function repo_list(dialog_ctx) { } async function remove_repo(repo_url) { - dialog.loader(dialog_ctx, "Removing repository..."); + dialog.loader(dialog_ctx, `Removing repository '${repo_url}'...`); try { await haketilodb.del_repo(repo_url); var removing_ok = true; } finally { - if (!removing_ok) - dialog.error(dialog_ctx, "Failed to remove repository :("); + if (!removing_ok) { + dialog.error(dialog_ctx, + `Failed to remove repository '${repo_url}' :(`); + } dialog.close(dialog_ctx); } } async function create_repo(repo_url) { - repo_url = validate_normalize_repo_url(repo_url); + repo_url = validate_normalize(repo_url); - dialog.loader(dialog_ctx, "Adding repository..."); + dialog.loader(dialog_ctx, `Adding repository '${repo_url}'...`); try { await haketilodb.set_repo(repo_url); var adding_ok = true; } finally { if (!adding_ok) - dialog.error(dialog_ctx, "Failed to add repository :("); + dialog.error(dialog_ctx, `Failed to add repository '${repo_url}' :(`); dialog.close(dialog_ctx); } @@ -284,7 +286,7 @@ async function repo_list(dialog_ctx) { if (old_repo_url === new_repo_url) return; - new_repo_url = validate_normalize_repo_url(new_repo_url); + new_repo_url = validate_normalize(new_repo_url); dialog.loader(dialog_ctx, "Replacing repository..."); @@ -319,3 +321,117 @@ async function repo_list(dialog_ctx) { return list; } #EXPORT repo_list + +async function blocking_allowing_lists(dialog_ctx) { + function validate_normalize(url_pattern) { + try { + return validate_normalize_url_pattern(url_pattern); + } catch(e) { + dialog.error(dialog_ctx, e); + throw e; + } + } + + async function default_allowing_on(url_pattern, allow) { + dialog.loader(dialog_ctx, + `Setting default scripts blocking policy on '${url_pattern}'...`); + + try { + await haketilodb.set_default_allowing(url_pattern); + var default_allowing_ok = true; + } finally { + if (!default_allowing_ok) { + dialog.error(dialog_ctx, + `Failed to remove rule for '${url_pattern}' :(`); + } + + dialog.close(dialog_ctx); + } + } + + async function set_allowing_on(url_pattern, allow) { + url_pattern = validate_normalize(url_pattern); + + const [action, action_cap] = allow ? + ["allowing", "Allowing"] : ["blocking", "Blocking"]; + dialog.loader(dialog_ctx, `${action_cap} scripts on '${url_pattern}'...`); + + try { + await haketilodb.set_allowed(url_pattern, allow); + var set_allowing_ok = true; + } finally { + if (!set_allowing_ok) + dialog.error(dialog_ctx, + `Failed to write ${action} rule for '${url_pattern}' :(`); + + dialog.close(dialog_ctx); + } + } + + async function replace_allowing_on(old_pattern, new_pattern, allow) { + new_pattern = validate_normalize(new_pattern); + if (old_pattern === new_pattern) + return; + + const action = allow ? "allowing" : "blocking"; + dialog.loader(dialog_ctx, `Rewriting script ${action} rule...`); + + try { + await haketilodb.set_allowed(new_pattern, allow); + await haketilodb.set_default_allowing(old_pattern); + var replace_allowing_ok = true; + } finally { + if (!replace_allowing_ok) + dialog.error(dialog_ctx, `Failed to rewrite ${action} rule :(`); + + dialog.close(dialog_ctx); + } + } + + let blocking_list, allowing_list; + + function onchange(change) { + if (change.new_val) { + if (change.new_val.allow) + var [to_add, to_remove] = [allowing_list, blocking_list]; + else + var [to_add, to_remove] = [blocking_list, allowing_list]; + + to_add.add(change.key); + to_remove.remove(change.key); + } else { + blocking_list.remove(change.key); + allowing_list.remove(change.key); + } + } + + dialog.loader(dialog_ctx, "Loading script blocking settings..."); + const [tracking, items] = await haketilodb.track.blocking(onchange); + dialog.close(dialog_ctx); + + let untrack_called = 0; + function untrack() { + if (++untrack_called === 2) + haketilodb.untrack(tracking); + } + + const lists = []; + for (const allow of [false, true]) { + lists[allow + 0] = + new TextEntryList(dialog_ctx, untrack, + pattern => default_allowing_on(pattern), + pattern => set_allowing_on(pattern, allow), + (p1, p2) => replace_allowing_on(p1, p2, allow)); + } + [blocking_list, allowing_list] = lists; + + for (const item of items) { + if (item.allow) + allowing_list.add(item.pattern); + else + blocking_list.add(item.pattern); + } + + return lists; +} +#EXPORT blocking_allowing_lists -- cgit v1.2.3