From 099124c49ea806626c8a48655ec678653f0ea3ed Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Wed, 24 May 2023 14:00:41 -0400 Subject: [PATCH] feat: global switch for disabling federation, + test --- public/language/en-GB/admin/menu.json | 1 + .../en-GB/admin/settings/activitypub.json | 7 +++++ src/middleware/index.js | 2 +- src/views/admin/partials/navigation.tpl | 1 + src/views/admin/settings/activitypub.tpl | 20 +++++++++++++ test/activitypub.js | 29 +++++++++++++++++++ 6 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 public/language/en-GB/admin/settings/activitypub.json create mode 100644 src/views/admin/settings/activitypub.tpl diff --git a/public/language/en-GB/admin/menu.json b/public/language/en-GB/admin/menu.json index 6e30be22b3..913c74f475 100644 --- a/public/language/en-GB/admin/menu.json +++ b/public/language/en-GB/admin/menu.json @@ -38,6 +38,7 @@ "settings/tags": "Tags", "settings/notifications": "Notifications", "settings/api": "API Access", + "settings/activitypub": "Federation (ActivityPub)", "settings/sounds": "Sounds", "settings/social": "Social", "settings/cookies": "Cookies", diff --git a/public/language/en-GB/admin/settings/activitypub.json b/public/language/en-GB/admin/settings/activitypub.json new file mode 100644 index 0000000000..989eeaf6f3 --- /dev/null +++ b/public/language/en-GB/admin/settings/activitypub.json @@ -0,0 +1,7 @@ +{ + "intro-lead": "What is Federation?", + "intro-body": "NodeBB is able to communicate with other NodeBB instances that support it. This is achieved through a protocol called ActivityPub. If enabled, NodeBB will also be able to communicate with other apps and websites that use ActivityPub (e.g. Mastodon, Peertube, etc.)", + + "general": "General", + "enabled": "Enable Federation" +} \ No newline at end of file diff --git a/src/middleware/index.js b/src/middleware/index.js index 4a9ebb44f8..f8ba614ab2 100644 --- a/src/middleware/index.js +++ b/src/middleware/index.js @@ -302,7 +302,7 @@ middleware.proceedOnActivityPub = (req, res, next) => { // For whatever reason, express accepts does not recognize "profile" as a valid differentiator // Therefore, manual header parsing is used here. const { accept } = req.headers; - if (!accept) { + if (!accept || !meta.config.activityPubEnabled) { return next('route'); } diff --git a/src/views/admin/partials/navigation.tpl b/src/views/admin/partials/navigation.tpl index 8c89f6a702..6c842c2abf 100644 --- a/src/views/admin/partials/navigation.tpl +++ b/src/views/admin/partials/navigation.tpl @@ -86,6 +86,7 @@ [[admin/menu:settings/pagination]] [[admin/menu:settings/notifications]] [[admin/menu:settings/api]] + [[admin/menu:settings/activitypub]] [[admin/menu:settings/cookies]] [[admin/menu:settings/web-crawler]] [[admin/menu:settings/advanced]] diff --git a/src/views/admin/settings/activitypub.tpl b/src/views/admin/settings/activitypub.tpl new file mode 100644 index 0000000000..a32920619a --- /dev/null +++ b/src/views/admin/settings/activitypub.tpl @@ -0,0 +1,20 @@ + + +

[[admin/settings/activitypub:intro-lead]]

+

[[admin/settings/activitypub:intro-body]]

+ +
+ +
+
[[admin/settings/activitypub:general]]
+
+
+
+ + +
+
+
+
+ + diff --git a/test/activitypub.js b/test/activitypub.js index d41ee508da..5193fdfbee 100644 --- a/test/activitypub.js +++ b/test/activitypub.js @@ -8,10 +8,19 @@ const db = require('./mocks/databasemock'); const slugify = require('../src/slugify'); const utils = require('../src/utils'); +const meta = require('../src/meta'); const user = require('../src/user'); const privileges = require('../src/privileges'); describe('ActivityPub integration', () => { + before(() => { + meta.config.activityPubEnabled = 1; + }); + + after(() => { + delete meta.config.activityPubEnabled; + }); + describe('WebFinger endpoint', () => { let uid; let slug; @@ -98,6 +107,26 @@ describe('ActivityPub integration', () => { uid = await user.create({ username: slug }); }); + it('should return regular user profile html if federation is disabled', async () => { + delete meta.config.activityPubEnabled; + + const response = await request(`${nconf.get('url')}/user/${slug}`, { + method: 'get', + followRedirect: true, + simple: false, + resolveWithFullResponse: true, + headers: { + Accept: 'text/html', + }, + }); + + assert(response); + assert.strictEqual(response.statusCode, 200); + assert(response.body.startsWith('')); + + meta.config.activityPubEnabled = 1; + }); + it('should return regular user profile html if Accept header is not ActivityPub-related', async () => { const response = await request(`${nconf.get('url')}/user/${slug}`, { method: 'get',