From f5e2a0f49ac64fefdc8df0d94ea64b31d6e121a2 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 20 Mar 2026 11:15:24 -0400 Subject: [PATCH] fix: #14112, federation/rules and relays ACP pages not refreshing table properly on changes, basic form validation --- .../language/en-GB/admin/settings/activitypub.json | 1 + public/src/admin/federation/relays.js | 9 ++++++--- public/src/admin/federation/rules.js | 12 +++++++++--- src/controllers/write/admin.js | 5 ++++- src/views/admin/partials/activitypub/relays.tpl | 2 +- src/views/admin/partials/activitypub/rules.tpl | 2 +- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/public/language/en-GB/admin/settings/activitypub.json b/public/language/en-GB/admin/settings/activitypub.json index 64508849aa..677af75cd7 100644 --- a/public/language/en-GB/admin/settings/activitypub.json +++ b/public/language/en-GB/admin/settings/activitypub.json @@ -39,6 +39,7 @@ "relays.state-0": "Pending", "relays.state-1": "Receiving only", "relays.state-2": "Active", + "relays.errors.invalid-url": "Please enter a valid URL", "server-filtering": "Filtering", "count": "This NodeBB is currently aware of %1 server(s)", diff --git a/public/src/admin/federation/relays.js b/public/src/admin/federation/relays.js index 190720318d..77fade6c1b 100644 --- a/public/src/admin/federation/relays.js +++ b/public/src/admin/federation/relays.js @@ -24,7 +24,7 @@ function setupRelays() { case 'relays.remove': { const url = subselector.closest('tr').getAttribute('data-url'); del(`/admin/activitypub/relays/${encodeURIComponent(url)}`, {}).then(async (data) => { - const html = await app.parseAndTranslate('admin/settings/activitypub', 'relays', { relays: data }); + const html = await app.parseAndTranslate('admin/federation/relays', 'relays', { relays: data }); const tbodyEl = document.querySelector('#relays tbody'); if (tbodyEl) { $(tbodyEl).html(html); @@ -41,10 +41,13 @@ function throwModal() { render('admin/partials/activitypub/relays', {}).then(function (html) { const submit = function () { const formEl = modal.find('form').get(0); - const payload = Object.fromEntries(new FormData(formEl)); + if (!formEl.reportValidity()) { + return false; + } + const payload = Object.fromEntries(new FormData(formEl)); post('/admin/activitypub/relays', payload).then(async (data) => { - const html = await app.parseAndTranslate('admin/settings/activitypub', 'relays', { relays: data }); + const html = await app.parseAndTranslate('admin/federation/relays', 'relays', { relays: data }); const tbodyEl = document.querySelector('#relays tbody'); if (tbodyEl) { $(tbodyEl).html(html); diff --git a/public/src/admin/federation/rules.js b/public/src/admin/federation/rules.js index fca956e567..78b058886d 100644 --- a/public/src/admin/federation/rules.js +++ b/public/src/admin/federation/rules.js @@ -29,7 +29,7 @@ function setupRules() { case 'rules.delete': { const rid = subselector.closest('tr').getAttribute('data-rid'); del(`/admin/activitypub/rules/${rid}`, {}).then(async (data) => { - const html = await render('admin/settings/activitypub', { rules: data }, 'rules'); + const html = await render('admin/federation/rules', { rules: data }, 'rules'); const tbodyEl = document.querySelector('#rules tbody'); if (tbodyEl) { tbodyEl.innerHTML = html; @@ -68,15 +68,21 @@ function throwModal() { render('admin/partials/activitypub/rules', {}).then(function (html) { const submit = function () { const formEl = modal.find('form').get(0); - const payload = Object.fromEntries(new FormData(formEl)); + if (!formEl.reportValidity()) { + return false; + } + const payload = Object.fromEntries(new FormData(formEl)); post('/admin/activitypub/rules', payload).then(async (data) => { - const html = await render('admin/settings/activitypub', { rules: data }, 'rules'); + const html = await render('admin/federation/rules', { rules: data }, 'rules'); const tbodyEl = document.querySelector('#rules tbody'); if (tbodyEl) { tbodyEl.innerHTML = html; } + modal.modal('hide'); }).catch(error); + + return false; }; const modal = bootbox.dialog({ title: '[[admin/settings/activitypub:rules.add]]', diff --git a/src/controllers/write/admin.js b/src/controllers/write/admin.js index 53662f6b34..65621bc853 100644 --- a/src/controllers/write/admin.js +++ b/src/controllers/write/admin.js @@ -110,8 +110,11 @@ Admin.activitypub.reorderRules = async (req, res) => { helpers.formatApiResponse(200, res, await activitypub.rules.list()); }; -Admin.activitypub.addRelay = async (req, res) => { +Admin.activitypub.addRelay = async (req, res, next) => { const { url } = req.body; + if (!url) { + return next(); + } await activitypub.relays.add(url); helpers.formatApiResponse(200, res, await activitypub.relays.list()); diff --git a/src/views/admin/partials/activitypub/relays.tpl b/src/views/admin/partials/activitypub/relays.tpl index 8f53b167f0..be8fd4e510 100644 --- a/src/views/admin/partials/activitypub/relays.tpl +++ b/src/views/admin/partials/activitypub/relays.tpl @@ -6,6 +6,6 @@
- +
\ No newline at end of file diff --git a/src/views/admin/partials/activitypub/rules.tpl b/src/views/admin/partials/activitypub/rules.tpl index 33273942b5..eaf463f6dc 100644 --- a/src/views/admin/partials/activitypub/rules.tpl +++ b/src/views/admin/partials/activitypub/rules.tpl @@ -14,7 +14,7 @@
- +