From 41cd0f7f33a77a579b8e020b4c2916eaae05a42e Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Sun, 5 Feb 2023 10:42:30 -0700 Subject: [PATCH] Fix local Actor URLs, add addFollowing() API --- core/activitypub/actor.js | 13 +++--- core/activitypub/collection.js | 77 ++++++++++++++++++++-------------- core/database.js | 2 +- core/http_util.js | 11 +++++ 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/core/activitypub/actor.js b/core/activitypub/actor.js index efe8c4b9..979b2f1e 100644 --- a/core/activitypub/actor.js +++ b/core/activitypub/actor.js @@ -19,7 +19,6 @@ const ActivityPubSettings = require('./settings'); const ActivityPubObject = require('./object'); const { ActivityStreamMediaType } = require('./const'); const apDb = require('../database').dbs.activitypub; -const Config = require('../config').get; // deps const _ = require('lodash'); @@ -132,11 +131,13 @@ module.exports = class Actor extends ActivityPubObject { // value: 'Mateo@21:1/121', // }, // ], - bbsInfo: { - boardName: Config().general.boardName, - memberSince: user.getProperty(UserProps.AccountCreated), - affiliations: user.getProperty(UserProps.Affiliations) || '', - }, + + // :TODO: re-enable once a spec is defined; board should prob be a object with connection info, etc. + // bbsInfo: { + // boardName: Config().general.boardName, + // memberSince: user.getProperty(UserProps.AccountCreated), + // affiliations: user.getProperty(UserProps.Affiliations) || '', + // }, }; addImage(obj, 'icon'); diff --git a/core/activitypub/collection.js b/core/activitypub/collection.js index b8fb49d4..a95753d9 100644 --- a/core/activitypub/collection.js +++ b/core/activitypub/collection.js @@ -26,27 +26,29 @@ module.exports = class Collection extends ActivityPubObject { const headers = { Accept: ActivityStreamMediaType, }; - getJson(collectionUrl, { headers }, (err, collection) => { - if (err) { - return cb(err); + getJson( + collectionUrl, + { headers, validContentTypes: [ActivityStreamMediaType] }, + (err, collection) => { + if (err) { + return cb(err); + } + + collection = new Collection(collection); + if (!collection.isValid()) { + return cb(Errors.Invalid('Invalid Collection')); + } + + const { totalItems, type, id, summary } = collection; + + return cb(null, { + totalItems, + type, + id, + summary, + }); } - - // :TODO: validate headers? - - collection = new Collection(collection); - if (!collection.isValid()) { - return cb(Errors.Invalid('Invalid Collection')); - } - - const { totalItems, type, id, summary } = collection; - - return cb(null, { - totalItems, - type, - id, - summary, - }); - }); + ); } static followers(collectionId, page, cb) { @@ -71,14 +73,14 @@ module.exports = class Collection extends ActivityPubObject { static addFollower(owningUser, followingActor, webServer, ignoreDupes, cb) { const collectionId = - makeUserUrl(webServer, owningUser, '/ap/collections/') + '/followers'; + makeUserUrl(webServer, owningUser, '/ap/users/') + '/followers'; return Collection.addToCollection( 'followers', owningUser, collectionId, - followingActor.id, + followingActor.id, // Actor following owningUser followingActor, - false, + false, // we'll check dynamically when queried ignoreDupes, cb ); @@ -86,12 +88,12 @@ module.exports = class Collection extends ActivityPubObject { static addFollowRequest(owningUser, requestingActor, webServer, ignoreDupes, cb) { const collectionId = - makeUserUrl(webServer, owningUser, '/ap/collections/') + '/follow-requests'; + makeUserUrl(webServer, owningUser, '/ap/users/') + '/follow-requests'; return Collection.addToCollection( 'follow-requests', owningUser, collectionId, - requestingActor.id, + requestingActor.id, // Actor requesting to follow owningUser requestingActor, true, ignoreDupes, @@ -99,13 +101,27 @@ module.exports = class Collection extends ActivityPubObject { ); } + static addFollowing(owningUser, followingActor, webServer, ignoreDupes, cb) { + const collectionId = + makeUserUrl(webServer, owningUser, '/ap/users/') + '/following'; + return Collection.addToCollection( + 'following', + owningUser, + collectionId, + followingActor.id, // Actor owningUser is following + followingActor, + false, // we'll check dynamically when queried + ignoreDupes, + cb + ); + } + static outbox(collectionId, page, cb) { return Collection.publicOrderedById('outbox', collectionId, page, null, cb); } static addOutboxItem(owningUser, outboxItem, isPrivate, webServer, ignoreDupes, cb) { - const collectionId = - makeUserUrl(webServer, owningUser, '/ap/collections/') + '/outbox'; + const collectionId = makeUserUrl(webServer, owningUser, '/ap/users/') + '/outbox'; return Collection.addToCollection( 'outbox', owningUser, @@ -119,8 +135,7 @@ module.exports = class Collection extends ActivityPubObject { } static addInboxItem(inboxItem, owningUser, webServer, ignoreDupes, cb) { - const collectionId = - makeUserUrl(webServer, owningUser, '/ap/collections/') + '/inbox'; + const collectionId = makeUserUrl(webServer, owningUser, '/ap/users/') + '/inbox'; return Collection.addToCollection( 'inbox', owningUser, @@ -282,9 +297,9 @@ module.exports = class Collection extends ActivityPubObject { ); } - // e.g. http://somewhere.com/_enig/ap/collections/NuSkooler/followers + // e.g. http://somewhere.com/_enig/ap/users/NuSkooler/followers const collectionId = - makeUserUrl(webServer, owningUser, '/ap/collections/') + `/${collectionName}`; + makeUserUrl(webServer, owningUser, '/ap/users/') + `/${collectionName}`; if (!page) { return apDb.get( diff --git a/core/database.js b/core/database.js index 6277a71d..bab1ffbf 100644 --- a/core/database.js +++ b/core/database.js @@ -493,7 +493,7 @@ dbs.message.run( // ActivityPub Collections of various types such as followers, following, likes, ... dbs.activitypub.run( `CREATE TABLE IF NOT EXISTS collection ( - collection_id VARCHAR NOT NULL, -- ie: http://somewhere.com/_enig/ap/collections/NuSkooler/followers + collection_id VARCHAR NOT NULL, -- ie: http://somewhere.com/_enig/ap/users/NuSkooler/followers name VARCHAR NOT NULL, -- examples: followers, follows, ... timestamp DATETIME NOT NULL, -- Timestamp in which this entry was created owner_actor_id VARCHAR NOT NULL, -- Local, owning Actor ID, or the #Public magic collection ID diff --git a/core/http_util.js b/core/http_util.js index 0474fc1c..f9dd540e 100644 --- a/core/http_util.js +++ b/core/http_util.js @@ -18,6 +18,17 @@ function getJson(url, options, cb) { return cb(err); } + if (Array.isArray(options.validContentTypes)) { + const contentType = res.headers['content-type'] || ''; + if ( + !options.validContentTypes.some(ct => { + return contentType.startsWith(ct); + }) + ) { + return cb(Errors.HttpError(`Invalid Content-Type: ${contentType}`)); + } + } + Log.debug({ url: url, body: body }, 'Response from getJson'); let parsed; try {