From fd8bbeebcf8fee63da381377ce19f4407ce3550c Mon Sep 17 00:00:00 2001 From: Fabien O'Carroll Date: Thu, 16 May 2024 17:12:16 +0700 Subject: [PATCH] Added support for GET /inbox/:owner ref https://linear.app/tryghost/issue/MOM-127 We're gonna want auth & filtering on this long term, but for now whilst in development it's fine as is. --- .../ghost/src/core/activitypub/actor.entity.ts | 4 ++++ .../src/core/activitypub/jsonld.service.ts | 17 +++++++++++++++++ .../controllers/activitypub.controller.test.ts | 6 ++++++ .../controllers/activitypub.controller.ts | 11 +++++++++++ 4 files changed, 38 insertions(+) diff --git a/ghost/ghost/src/core/activitypub/actor.entity.ts b/ghost/ghost/src/core/activitypub/actor.entity.ts index 30101e7ce7..f339e62c20 100644 --- a/ghost/ghost/src/core/activitypub/actor.entity.ts +++ b/ghost/ghost/src/core/activitypub/actor.entity.ts @@ -68,6 +68,10 @@ export class Actor extends Entity { return this.username; } + get inbox() { + return this.attr.inbox; + } + get outbox() { return this.attr.outbox; } diff --git a/ghost/ghost/src/core/activitypub/jsonld.service.ts b/ghost/ghost/src/core/activitypub/jsonld.service.ts index 3800390fc4..944397a4d0 100644 --- a/ghost/ghost/src/core/activitypub/jsonld.service.ts +++ b/ghost/ghost/src/core/activitypub/jsonld.service.ts @@ -45,6 +45,23 @@ export class JSONLDService { items: actor.followers.map(item => item.id.getValue(this.url)) }; } + + async getInbox(owner: ObjectID) { + const actor = await this.repository.getOne(owner); + if (!actor) { + return null; + } + const json = actor.getJSONLD(this.url); + return { + '@context': 'https://www.w3.org/ns/activitystreams', + id: json.inbox, + summary: `Inbox for ${actor.username}`, + type: 'OrderedCollection', + totalItems: actor.inbox.length, + orderedItems: actor.inbox.map(activity => activity.getJSONLD(this.url)) + }; + } + async getOutbox(owner: ObjectID) { const actor = await this.repository.getOne(owner); if (!actor) { diff --git a/ghost/ghost/src/http/frontend/controllers/activitypub.controller.test.ts b/ghost/ghost/src/http/frontend/controllers/activitypub.controller.test.ts index 9ad14fa81c..f96828c076 100644 --- a/ghost/ghost/src/http/frontend/controllers/activitypub.controller.test.ts +++ b/ghost/ghost/src/http/frontend/controllers/activitypub.controller.test.ts @@ -103,6 +103,12 @@ describe('ActivityPubController', function () { .expect(200); }); + it('Can handle requests to get the inbox', async function () { + await request(app.getHttpServer()) + .get('/activitypub/inbox/deadbeefdeadbeefdeadbeef') + .expect(200); + }); + it('Can handle requests to get the following', async function () { await request(app.getHttpServer()) .get('/activitypub/following/deadbeefdeadbeefdeadbeef') diff --git a/ghost/ghost/src/http/frontend/controllers/activitypub.controller.ts b/ghost/ghost/src/http/frontend/controllers/activitypub.controller.ts index a662cdee86..bbf245d42a 100644 --- a/ghost/ghost/src/http/frontend/controllers/activitypub.controller.ts +++ b/ghost/ghost/src/http/frontend/controllers/activitypub.controller.ts @@ -24,6 +24,17 @@ export class ActivityPubController { return this.service.getActor(ObjectID.createFromHexString(id)); } + @Header('Cache-Control', 'no-store') + @Header('Content-Type', 'application/activity+json') + @Roles(['Anon']) + @Get('inbox/:owner') + async getInbox(@Param('owner') owner: unknown) { + if (typeof owner !== 'string') { + throw new Error('Bad Request'); + } + return this.service.getInbox(ObjectID.createFromHexString(owner)); + } + @Header('Cache-Control', 'no-store') @Header('Content-Type', 'application/activity+json') @Roles(['Anon'])