From a209a3dc2930dbb3e087343555ab8c74ea101006 Mon Sep 17 00:00:00 2001 From: Madeline <46743919+MaddyUnderStars@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:13:51 +0000 Subject: [PATCH] fix body parser config add user inbox for dm channels fix missing prop in federated keys generation --- src/activitypub/Server.ts | 10 +++++- src/activitypub/federation/transforms.ts | 5 +-- .../routes/users/#user_id/inbox.ts | 35 +++++++++++++++++++ src/util/entities/FederationKeys.ts | 5 ++- 4 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 src/activitypub/routes/users/#user_id/inbox.ts diff --git a/src/activitypub/Server.ts b/src/activitypub/Server.ts index 9b540c68f..16e894ec1 100644 --- a/src/activitypub/Server.ts +++ b/src/activitypub/Server.ts @@ -7,6 +7,7 @@ import { registerRoutes, setupMorganLogging, } from "@spacebar/util"; +import bodyParser from "body-parser"; import { Request, Response, Router } from "express"; import { Server, ServerOptions } from "lambert-server"; import path from "path"; @@ -32,7 +33,14 @@ export class FederationServer extends Server { this.app.set("json replacer", JSONReplacer); this.app.use(CORS); - this.app.use(BodyParser({ inflate: true, limit: "10mb" })); + this.app.use( + BodyParser({ + inflate: true, + limit: "10mb", + type: "application/activity+json", + }), + ); + this.app.use(bodyParser.urlencoded({ extended: true })); const app = this.app; const api = Router(); diff --git a/src/activitypub/federation/transforms.ts b/src/activitypub/federation/transforms.ts index 4ce6471ac..db7942610 100644 --- a/src/activitypub/federation/transforms.ts +++ b/src/activitypub/federation/transforms.ts @@ -235,7 +235,7 @@ export const transformPersonToUser = async (person: AP.Person) => { return await User.findOneOrFail({ where: { id: cachedKeys.actorId } }); } - await FederationKey.create({ + const keys = await FederationKey.create({ actorId: Snowflake.generate(), federatedId: url.toString(), domain: url.hostname, @@ -243,7 +243,8 @@ export const transformPersonToUser = async (person: AP.Person) => { type: ActorType.USER, }).save(); - return User.create({ + return await User.create({ + id: keys.actorId, username: person.preferredUsername, discriminator: url.hostname, bio: new TurndownService().turndown(person.summary), diff --git a/src/activitypub/routes/users/#user_id/inbox.ts b/src/activitypub/routes/users/#user_id/inbox.ts new file mode 100644 index 000000000..5414ab48c --- /dev/null +++ b/src/activitypub/routes/users/#user_id/inbox.ts @@ -0,0 +1,35 @@ +import { transformNoteToMessage } from "@spacebar/ap"; +import { route } from "@spacebar/api"; +import { Message, emitEvent } from "@spacebar/util"; +import { AP } from "activitypub-core-types"; +import { Request, Response, Router } from "express"; +import { HTTPError } from "lambert-server"; +const router = Router(); + +// TODO: check if the activity exists on the remote server +router.post("/", route({}), async (req: Request, res: Response) => { + const body = req.body as AP.Create; + + if (body.type != "Create") throw new HTTPError("not implemented"); + + const object = Array.isArray(body.object) ? body.object[0] : body.object; + if (!object) return res.status(400); + if (!("type" in object) || object.type != "Note") + throw new HTTPError("must be Note"); + const message = await transformNoteToMessage(object as AP.Note); + + if ((await Message.count({ where: { nonce: object.id!.toString() } })) != 0) + return res.status(200); + + await message.save(); + + await emitEvent({ + event: "MESSAGE_CREATE", + channel_id: message.channel_id, + data: message.toJSON(), + }); + + return res.status(200); +}); + +export default router; diff --git a/src/util/entities/FederationKeys.ts b/src/util/entities/FederationKeys.ts index f3f15de50..d8774f465 100644 --- a/src/util/entities/FederationKeys.ts +++ b/src/util/entities/FederationKeys.ts @@ -45,10 +45,13 @@ export class FederationKey extends BaseClassWithoutId { // Lazy loading config to prevent circular dep const { Config } = await import("../util/Config"); + const { accountDomain, host } = Config.get().federation; + const keys = FederationKey.create({ actorId, type, - domain: Config.get().federation.accountDomain, + federatedId: `https://${host}/federation/${type}/${actorId}`, + domain: accountDomain, ...(await generateKeyPair("rsa", { modulusLength: 4096, publicKeyEncoding: {