From d5446cdb51c18e5ccfe41060615b7887dd8fd8d8 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Tue, 24 Jan 2023 18:11:28 -0700 Subject: [PATCH] Cleanup and placeholder --- core/activitypub/activity.js | 12 +++++++ core/activitypub/collection.js | 30 +++++++++++++++++ core/activitypub/const.js | 19 +++++++++++ .../content/web_handlers/activitypub.js | 33 ++++++++++++++++--- misc/menu_templates/private_mail.in.hjson | 2 +- 5 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 core/activitypub/const.js diff --git a/core/activitypub/activity.js b/core/activitypub/activity.js index 83dc3e28..a5af0416 100644 --- a/core/activitypub/activity.js +++ b/core/activitypub/activity.js @@ -4,6 +4,7 @@ const ActivityPubObject = require('./object'); const { Errors } = require('../enig_error'); const UserProps = require('../user_property'); const { postJson } = require('../http_util'); +const { getISOTimestampString } = require('../database'); // deps const _ = require('lodash'); @@ -45,6 +46,17 @@ module.exports = class Activity extends ActivityPubObject { }); } + static makeTombstone(obj) { + const deleted = getISOTimestampString(); + return new Activity({ + id: obj.id, + type: 'Tombstone', + deleted, + published: deleted, + updated: deleted, + }); + } + sendTo(actorUrl, fromUser, webServer, cb) { const privateKey = fromUser.getProperty(UserProps.PrivateActivityPubSigningKey); if (_.isEmpty(privateKey)) { diff --git a/core/activitypub/collection.js b/core/activitypub/collection.js index 8bef5727..3f719208 100644 --- a/core/activitypub/collection.js +++ b/core/activitypub/collection.js @@ -54,6 +54,17 @@ module.exports = class Collection extends ActivityPubObject { ); } + static addFollowRequest(owningUser, requestingActor, cb) { + return Collection.addToCollection( + 'follow_requests', + owningUser, + requestingActor.id, + requestingActor, + true, + cb + ); + } + static outbox(owningUser, page, webServer, cb) { return Collection.getOrdered( 'outbox', @@ -207,6 +218,25 @@ module.exports = class Collection extends ActivityPubObject { ); } + // https://www.w3.org/TR/activitypub/#update-activity-inbox + static updateCollectionEntry(collectionName, objectId, obj, cb) { + if (!isString(obj)) { + obj = JSON.stringify(obj); + } + + // :TODO: The receiving server MUST take care to be sure that the Update is authorized to modify its object. At minimum, this may be done by ensuring that the Update and its object are of same origin. + + apDb.run( + `UPDATE collection + SET obj_json = ?, timestamp = ? + WHERE name = ? AND obj_id = ?;`, + [obj, collectionName, getISOTimestampString(), objectId], + err => { + return cb(err); + } + ); + } + static addToCollection(collectionName, owningUser, objectId, obj, isPrivate, cb) { if (!isString(obj)) { obj = JSON.stringify(obj); diff --git a/core/activitypub/const.js b/core/activitypub/const.js new file mode 100644 index 00000000..b5602770 --- /dev/null +++ b/core/activitypub/const.js @@ -0,0 +1,19 @@ +exports.ActivityStreamsContext = 'https://www.w3.org/ns/activitystreams'; + +const WellKnownActivity = { + Create: 'Create', + Update: 'Update', + Delete: 'Delete', + Follow: 'Follow', + Accept: 'Accept', + Reject: 'Reject', + Add: 'Add', + Remove: 'Remove', + Like: 'Like', + Announce: 'Announce', + Undo: 'Undo', +}; +exports.WellKnownActivity = WellKnownActivity; + +const WellKnownActivityTypes = Object.values(WellKnownActivity); +exports.WellKnownActivityTypes = WellKnownActivityTypes; diff --git a/core/servers/content/web_handlers/activitypub.js b/core/servers/content/web_handlers/activitypub.js index 65bab44f..7fb6fbdf 100644 --- a/core/servers/content/web_handlers/activitypub.js +++ b/core/servers/content/web_handlers/activitypub.js @@ -203,6 +203,9 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule { resp ); + case 'Update': + return this._inboxUpdateRequestHandler(activity, req, resp); + case 'Undo': return this._inboxUndoRequestHandler(activity, req, resp); @@ -378,6 +381,8 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule { return this.webServer.internalServerError(resp, err); } + // :TODO: support a template here + resp.writeHead(200, { 'Content-Type': 'text/html' }); return resp.end(note.content); }); @@ -431,6 +436,11 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule { _inboxFollowRequestHandler(activity, remoteActor, user, resp) { this.log.info({ user_id: user.userId, actor: activity.actor }, 'Follow request'); + const ok = () => { + resp.writeHead(200, { 'Content-Type': 'text/html' }); + return resp.end(''); + }; + // // If the user blindly accepts Followers, we can persist // and send an 'Accept' now. Otherwise, we need to queue this @@ -440,16 +450,29 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule { const activityPubSettings = ActivityPubSettings.fromUser(user); if (!activityPubSettings.manuallyApproveFollowers) { this._recordAcceptedFollowRequest(user, remoteActor, activity); + return ok(); } else { - // :TODO: queue the request - } + Collection.addFollowRequest(user, remoteActor, err => { + if (err) { + return this.internalServerError(resp, err); + } - resp.writeHead(200, { 'Content-Type': 'text/html' }); - return resp.end(''); + return ok(); + }); + } + } + + _inboxUpdateRequestHandler(activity, req, resp) { + this.log.info({ actor: activity.actor }, 'Update Activity request'); + + return this.webServer.notImplemented(resp); + + // Collection.updateCollectionEntry('inbox', activity.id, activity, err => { + // }); } _inboxUndoRequestHandler(activity, req, resp) { - this.log.info({ actor: activity.actor }, 'Undo request'); + this.log.info({ actor: activity.actor }, 'Undo Activity request'); const url = new URL(req.url, `https://${req.headers.host}`); const accountName = this._accountNameFromUserPath(url, 'inbox'); diff --git a/misc/menu_templates/private_mail.in.hjson b/misc/menu_templates/private_mail.in.hjson index e27314dc..2914a11a 100644 --- a/misc/menu_templates/private_mail.in.hjson +++ b/misc/menu_templates/private_mail.in.hjson @@ -69,7 +69,7 @@ } ] } - actionKeys: @reference: common.escToPrev + actionKeys: @reference:common.escToPrev } 1: { mci: {