Added initial support for Outbox to Actors

ref https://linear.app/tryghost/issue/MOM-32

This adds the basic building blocks for an Outbox for an Actor, currently it's
hardcoded - which'll let us at lest test integration with other platforms.

JSONLDService is an awful name, but it's late and this is a prototype.
This commit is contained in:
Fabien O'Carroll 2024-04-17 20:17:30 +07:00 committed by Fabien 'egg' O'Carroll
parent 1d1c33db1e
commit c51a434f64
3 changed files with 94 additions and 2 deletions

View File

@ -0,0 +1,51 @@
import {Inject} from '@nestjs/common';
import {ActorRepository} from './actor.repository';
import ObjectID from 'bson-objectid';
export class JSONLDService {
constructor(
@Inject('ActorRepository') private repository: ActorRepository,
@Inject('ActivityPubBaseURL') private url: URL
) {}
async getActor(id: ObjectID) {
const actor = await this.repository.getOne(id);
return actor?.getJSONLD(this.url);
}
async getPublicKey(owner: ObjectID) {
const actor = await this.repository.getOne(owner);
return actor?.getJSONLD(this.url).publicKey;
}
async getOutbox(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.outbox,
summary: `Outbox for ${actor.username}`,
type: 'OrderedCollection',
totalItems: 1,
orderedItems: [{
type: 'Create',
actor: json.id,
to: [
'https://www.w3.org/ns/activitystreams#Public'
],
object: {
type: 'Note',
name: 'My First Note',
content: '<p>Hello, world!</p>',
attributedTo: json.id,
to: [
'https://www.w3.org/ns/activitystreams#Public'
]
}
}]
};
}
}

View File

@ -0,0 +1,38 @@
import {Controller, Get, Query} from '@nestjs/common';
import {Roles} from '../../../common/decorators/permissions.decorator';
import ObjectID from 'bson-objectid';
import {JSONLDService} from '../../../core/activitypub/jsonld.service';
@Controller('activitypub')
export class ActivityPubController {
constructor(
private readonly service: JSONLDService
) {}
@Roles(['Anon'])
@Get('actor')
async getActor(@Query('id') id: unknown) {
if (typeof id !== 'string') {
throw new Error('Bad Request');
}
return this.service.getActor(ObjectID.createFromHexString(id));
}
@Roles(['Anon'])
@Get('key')
async getKey(@Query('owner') owner: unknown) {
if (typeof owner !== 'string') {
throw new Error('Bad Request');
}
return this.service.getPublicKey(ObjectID.createFromHexString(owner));
}
@Roles(['Anon'])
@Get('outbox')
async getOutbox(@Query('owner') owner: unknown) {
if (typeof owner !== 'string') {
throw new Error('Bad Request');
}
return this.service.getOutbox(ObjectID.createFromHexString(owner));
}
}

View File

@ -3,13 +3,15 @@ import {ExampleController} from '../../http/admin/controllers/example.controller
import {ExampleService} from '../../core/example/example.service';
import {ExampleRepositoryInMemory} from '../../db/in-memory/example.repository.in-memory';
import {ActorRepositoryInMemory} from '../../db/in-memory/actor.repository.in-memory';
import {ActivityPubController} from '../../http/admin/controllers/activitypub.controller';
import {WebFingerService} from '../../core/activitypub/webfinger.service';
import {JSONLDService} from '../../core/activitypub/jsonld.service';
class AdminAPIModuleClass {}
export const AdminAPIModule: DynamicModule = {
module: AdminAPIModuleClass,
controllers: [ExampleController],
controllers: [ExampleController, ActivityPubController],
exports: [ExampleService, 'WebFingerService'],
providers: [
ExampleService,
@ -22,6 +24,7 @@ export const AdminAPIModule: DynamicModule = {
}, {
provide: 'WebFingerService',
useClass: WebFingerService
}
},
JSONLDService
]
};