From 110efb3de2e51ae17906cae006d7449d4784c046 Mon Sep 17 00:00:00 2001 From: Madeline <46743919+MaddyUnderStars@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:09:31 +1000 Subject: more fuckery --- src/activitypub/Server.ts | 4 +- src/activitypub/routes/user.ts | 29 +---------- src/activitypub/webfinger/index.ts | 64 ----------------------- src/activitypub/well-known/host-meta.ts | 20 ++++++++ src/activitypub/well-known/webfinger.ts | 68 +++++++++++++++++++++++++ src/util/entities/Channel.ts | 2 - src/util/entities/User.ts | 25 +++++++++ src/util/schemas/responses/WebfingerResponse.ts | 2 +- 8 files changed, 119 insertions(+), 95 deletions(-) delete mode 100644 src/activitypub/webfinger/index.ts create mode 100644 src/activitypub/well-known/host-meta.ts create mode 100644 src/activitypub/well-known/webfinger.ts (limited to 'src') diff --git a/src/activitypub/Server.ts b/src/activitypub/Server.ts index c497d2e6..373d7390 100644 --- a/src/activitypub/Server.ts +++ b/src/activitypub/Server.ts @@ -8,7 +8,8 @@ import { import { Request, Response, Router } from "express"; import { Server, ServerOptions } from "lambert-server"; import path from "path"; -import webfinger from "./webfinger"; +import hostMeta from "./well-known/host-meta"; +import webfinger from "./well-known/webfinger"; export class APServer extends Server { public declare options: ServerOptions; @@ -63,6 +64,7 @@ export class APServer extends Server { }); this.app.use("/.well-known/webfinger", webfinger); + this.app.use("/.well-known/host-meta", hostMeta); this.app.use(ErrorHandler); diff --git a/src/activitypub/routes/user.ts b/src/activitypub/routes/user.ts index 3366d711..d68df4d1 100644 --- a/src/activitypub/routes/user.ts +++ b/src/activitypub/routes/user.ts @@ -1,6 +1,5 @@ import { route } from "@spacebar/api"; -import { Config, User } from "@spacebar/util"; -import { APPerson } from "activitypub-types"; +import { User } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -11,29 +10,5 @@ router.get("/:id", route({}), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ where: { id } }); - const { webDomain } = Config.get().federation; - - const ret: APPerson = { - "@context": "https://www.w3.org/ns/activitystreams", - type: "Person", - id: `https://${webDomain}/fed/user/${user.id}`, - name: user.username, - preferredUsername: user.username, - summary: user.bio, - icon: user.avatar - ? [ - `${Config.get().cdn.endpointPublic}/avatars/${user.id}/${ - user.avatar - }`, - ] - : undefined, - - inbox: `https://${webDomain}/fed/user/${user.id}/inbox`, - outbox: `https://${webDomain}/fed/user/${user.id}/outbox`, - followers: `https://${webDomain}/fed/user/${user.id}/followers`, - following: `https://${webDomain}/fed/user/${user.id}/following`, - liked: `https://${webDomain}/fed/user/${user.id}/likeds`, - }; - - return res.json(ret); + return res.json(user.toAP()); }); diff --git a/src/activitypub/webfinger/index.ts b/src/activitypub/webfinger/index.ts deleted file mode 100644 index f1b49624..00000000 --- a/src/activitypub/webfinger/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { route } from "@spacebar/api"; -import { Channel, Config, User, WebfingerResponse } from "@spacebar/util"; -import { Request, Response, Router } from "express"; -import { HTTPError } from "lambert-server"; - -const router = Router(); -export default router; - -router.get( - "/", - route({ - query: { - resource: { - type: "string", - description: "Resource to locate", - }, - }, - responses: { - 200: { - body: "WebfingerResponse", - }, - }, - }), - async (req: Request, res: Response) => { - let resource = req.query.resource as string | undefined; - if (!resource) throw new HTTPError("Must specify resource"); - - // we know what you mean, bro - resource = resource.replace("acct:", ""); - - const [resourceId, resourceDomain] = resource.split("@"); - - const { webDomain } = Config.get().federation; - if (resourceDomain != webDomain) - throw new HTTPError("Resource could not be found", 404); - - const found = - (await User.findOne({ - where: { id: resourceId }, - select: ["id"], - })) || - (await Channel.findOne({ - where: { id: resourceId }, - select: ["id"], - })); - - if (!found) throw new HTTPError("Resource could not be found", 404); - - const type = found instanceof Channel ? "channel" : "user"; - - res.setHeader("Content-Type", "application/jrd+json; charset=utf-8"); - return res.json({ - subject: `acct:${resourceId}@${webDomain}`, // mastodon always returns acct so might as well - aliases: [`https://${webDomain}/fed/${type}/${resourceId}`], - links: [ - { - rel: "self", - type: "application/activity+json", - href: `https://${webDomain}/fed/${type}/${resourceId}`, - }, - ], - }); - }, -); diff --git a/src/activitypub/well-known/host-meta.ts b/src/activitypub/well-known/host-meta.ts new file mode 100644 index 00000000..2de2014c --- /dev/null +++ b/src/activitypub/well-known/host-meta.ts @@ -0,0 +1,20 @@ +import { route } from "@spacebar/api"; +import { Config } from "@spacebar/util"; +import { Request, Response, Router } from "express"; + +const router = Router(); +export default router; + +router.get("/", route({}), async (req: Request, res: Response) => { + res.setHeader("Content-Type", "application/xrd+xml"); + + const { webDomain } = Config.get().federation; + + const ret = ` + + + `; + + return res.send(ret); +}); diff --git a/src/activitypub/well-known/webfinger.ts b/src/activitypub/well-known/webfinger.ts new file mode 100644 index 00000000..c24a1477 --- /dev/null +++ b/src/activitypub/well-known/webfinger.ts @@ -0,0 +1,68 @@ +import { route } from "@spacebar/api"; +import { Channel, Config, User, WebfingerResponse } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +import { HTTPError } from "lambert-server"; + +const router = Router(); +export default router; + +router.get( + "/", + route({ + query: { + resource: { + type: "string", + description: "Resource to locate", + }, + }, + responses: { + 200: { + body: "WebfingerResponse", + }, + }, + }), + async (req: Request, res: Response) => { + let resource = req.query.resource as string | undefined; + if (!resource) throw new HTTPError("Must specify resource"); + + // we know what you mean, bro + resource = resource.replace("acct:", ""); + + const [resourceId, resourceDomain] = resource.split("@"); + + const { webDomain } = Config.get().federation; + if (resourceDomain != webDomain) + throw new HTTPError("Resource could not be found", 404); + + const found = + (await User.findOne({ + where: { id: resourceId }, + select: ["id"], + })) || + (await Channel.findOne({ + where: { id: resourceId }, + select: ["id"], + })); + + if (!found) throw new HTTPError("Resource could not be found", 404); + + const type = found instanceof Channel ? "channel" : "user"; + + res.setHeader("Content-Type", "application/jrd+json; charset=utf-8"); + return res.json({ + subject: `acct:${resourceId}@${webDomain}`, // mastodon always returns acct so might as well + aliases: [`https://${webDomain}/fed/${type}/${resourceId}`], + links: [ + { + rel: "self", + type: "application/activity+json", + href: `https://${webDomain}/fed/${type}/${resourceId}`, + }, + // { + // rel: "http://ostatus.org/schema/1.0/subscribe", + // href: `"https://${webDomain}/fed/authorize-follow?acct={uri}"`, + // }, + ], + }); + }, +); diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index 93265d07..33528d90 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -500,8 +500,6 @@ export class Channel extends BaseClass { inbox: `https://${webDomain}/fed/channel/${this.id}/inbox`, outbox: `https://${webDomain}/fed/channel/${this.id}/outbox`, followers: `https://${webDomain}/fed/channel/${this.id}/followers`, - following: `https://${webDomain}/fed/channel/${this.id}/following`, - liked: `https://${webDomain}/fed/channel/${this.id}/likeds`, }; } } diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index c6582b00..4263d39d 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -16,6 +16,7 @@ along with this program. If not, see . */ +import { APPerson } from "activitypub-types"; import { Request } from "express"; import { Column, @@ -271,6 +272,30 @@ export class User extends BaseClass { return user as UserPrivate; } + toAP(): APPerson { + const { webDomain } = Config.get().federation; + + return { + "@context": "https://www.w3.org/ns/activitystreams", + type: "Person", + id: `https://${webDomain}/fed/user/${user.id}`, + name: this.username, + preferredUsername: this.username, + summary: this.bio, + icon: this.avatar + ? [ + `${Config.get().cdn.endpointPublic}/avatars/${ + this.id + }/${this.avatar}`, + ] + : undefined, + + inbox: `https://${webDomain}/fed/user/${this.id}/inbox`, + outbox: `https://${webDomain}/fed/user/${this.id}/outbox`, + followers: `https://${webDomain}/fed/user/${this.id}/followers`, + }; + } + static async getPublicUser(user_id: string, opts?: FindOneOptions) { return await User.findOneOrFail({ where: { id: user_id }, diff --git a/src/util/schemas/responses/WebfingerResponse.ts b/src/util/schemas/responses/WebfingerResponse.ts index a3186a03..6b0ab0f9 100644 --- a/src/util/schemas/responses/WebfingerResponse.ts +++ b/src/util/schemas/responses/WebfingerResponse.ts @@ -1,6 +1,6 @@ interface WebfingerLink { rel: string; - type: string; + type?: string; href: string; template?: string; } -- cgit 1.5.1