mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
refactor: move activitypub-related middlewares to their own file
This commit is contained in:
@@ -14,7 +14,7 @@ const helpers = require('../helpers');
|
|||||||
|
|
||||||
const controller = module.exports;
|
const controller = module.exports;
|
||||||
|
|
||||||
controller.list = async function (req, res, next) {
|
controller.list = async function (req, res) {
|
||||||
const { topicsPerPage } = await user.getSettings(req.uid);
|
const { topicsPerPage } = await user.getSettings(req.uid);
|
||||||
const page = parseInt(req.query.page, 10) || 1;
|
const page = parseInt(req.query.page, 10) || 1;
|
||||||
const start = Math.max(0, (page - 1) * topicsPerPage);
|
const start = Math.max(0, (page - 1) * topicsPerPage);
|
||||||
|
|||||||
48
src/middleware/activitypub.js
Normal file
48
src/middleware/activitypub.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const meta = require('../meta');
|
||||||
|
const activitypub = require('../activitypub');
|
||||||
|
|
||||||
|
const middleware = module.exports;
|
||||||
|
|
||||||
|
middleware.enabled = async (req, res, next) => next(!meta.config.activitypubEnabled ? 'route' : undefined);
|
||||||
|
|
||||||
|
middleware.assertS2S = async function (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, 'content-type': contentType } = req.headers;
|
||||||
|
if (!(accept || contentType)) {
|
||||||
|
return next('route');
|
||||||
|
}
|
||||||
|
|
||||||
|
const acceptable = [
|
||||||
|
'application/activity+json',
|
||||||
|
'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||||
|
];
|
||||||
|
const pass = (accept && accept.split(',').some((value) => {
|
||||||
|
const parts = value.split(';').map(v => v.trim());
|
||||||
|
return acceptable.includes(value || parts[0]);
|
||||||
|
})) || (contentType && acceptable.includes(contentType));
|
||||||
|
|
||||||
|
if (!pass) {
|
||||||
|
return next('route');
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
middleware.validate = async function (req, res, next) {
|
||||||
|
// Checks the validity of the incoming payload against the sender and rejects on failure
|
||||||
|
const verified = await activitypub.verify(req);
|
||||||
|
if (!verified) {
|
||||||
|
return res.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity-check payload schema
|
||||||
|
const required = ['type'];
|
||||||
|
if (!required.every(prop => req.body.hasOwnProperty(prop))) {
|
||||||
|
return res.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
@@ -69,6 +69,7 @@ middleware.uploads = require('./uploads');
|
|||||||
require('./headers')(middleware);
|
require('./headers')(middleware);
|
||||||
require('./expose')(middleware);
|
require('./expose')(middleware);
|
||||||
middleware.assert = require('./assert');
|
middleware.assert = require('./assert');
|
||||||
|
middleware.activitypub = require('./activitypub');
|
||||||
|
|
||||||
middleware.stripLeadingSlashes = function stripLeadingSlashes(req, res, next) {
|
middleware.stripLeadingSlashes = function stripLeadingSlashes(req, res, next) {
|
||||||
const target = req.originalUrl.replace(relative_path, '');
|
const target = req.originalUrl.replace(relative_path, '');
|
||||||
@@ -306,43 +307,3 @@ middleware.handleMultipart = (req, res, next) => {
|
|||||||
|
|
||||||
multipartMiddleware(req, res, next);
|
multipartMiddleware(req, res, next);
|
||||||
};
|
};
|
||||||
|
|
||||||
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, 'content-type': contentType } = req.headers;
|
|
||||||
if (!meta.config.activitypubEnabled || !(accept || contentType)) {
|
|
||||||
return next('route');
|
|
||||||
}
|
|
||||||
|
|
||||||
const acceptable = [
|
|
||||||
'application/activity+json',
|
|
||||||
'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
|
||||||
];
|
|
||||||
const pass = (accept && accept.split(',').some((value) => {
|
|
||||||
const parts = value.split(';').map(v => v.trim());
|
|
||||||
return acceptable.includes(value || parts[0]);
|
|
||||||
})) || (contentType && acceptable.includes(contentType));
|
|
||||||
|
|
||||||
if (!pass) {
|
|
||||||
return next('route');
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
};
|
|
||||||
|
|
||||||
middleware.validateActivity = helpers.try(async (req, res, next) => {
|
|
||||||
// Checks the validity of the incoming payload against the sender and rejects on failure
|
|
||||||
const verified = await activitypub.verify(req);
|
|
||||||
if (!verified) {
|
|
||||||
return res.sendStatus(400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity-check payload schema
|
|
||||||
const required = ['type'];
|
|
||||||
if (!required.every(prop => req.body.hasOwnProperty(prop))) {
|
|
||||||
return res.sendStatus(400);
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -3,18 +3,20 @@
|
|||||||
const helpers = require('./helpers');
|
const helpers = require('./helpers');
|
||||||
|
|
||||||
module.exports = function (app, middleware, controllers) {
|
module.exports = function (app, middleware, controllers) {
|
||||||
helpers.setupPageRoute(app, '/world/:view?', controllers.activitypub.topics.list);
|
helpers.setupPageRoute(app, '/world/:view?', [middleware.activitypub.enabled], controllers.activitypub.topics.list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These controllers only respond if the sender is making an json+activitypub style call (i.e. S2S-only)
|
* These controllers only respond if the sender is making an json+activitypub style call (i.e. S2S-only)
|
||||||
|
*
|
||||||
|
* - See middleware.activitypub.assertS2S
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const middlewares = [middleware.proceedOnActivityPub, middleware.exposeUid];
|
const middlewares = [middleware.activitypub.enabled, middleware.activitypub.assertS2S, middleware.exposeUid];
|
||||||
|
|
||||||
app.get('/user/:userslug', middlewares, controllers.activitypub.getActor);
|
app.get('/user/:userslug', middlewares, controllers.activitypub.getActor);
|
||||||
|
|
||||||
app.get('/user/:userslug/inbox', middlewares, controllers.activitypub.getInbox);
|
app.get('/user/:userslug/inbox', middlewares, controllers.activitypub.getInbox);
|
||||||
app.post('/user/:userslug/inbox', [...middlewares, middleware.validateActivity], controllers.activitypub.postInbox);
|
app.post('/user/:userslug/inbox', [...middlewares, middleware.activitypub.validate], controllers.activitypub.postInbox);
|
||||||
|
|
||||||
app.get('/user/:userslug/outbox', middlewares, controllers.activitypub.getOutbox);
|
app.get('/user/:userslug/outbox', middlewares, controllers.activitypub.getOutbox);
|
||||||
app.post('/user/:userslug/outbox', middlewares, controllers.activitypub.postOutbox);
|
app.post('/user/:userslug/outbox', middlewares, controllers.activitypub.postOutbox);
|
||||||
|
|||||||
Reference in New Issue
Block a user