From a58c81c8e9dddb28ccf1d164c1aa2e60684b4198 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Tue, 9 Apr 2024 16:05:02 -1000 Subject: [PATCH] Implement federation of statuses --- bun.lockb | Bin 608724 -> 609140 bytes database/entities/Status.ts | 139 +++++++- database/entities/User.ts | 14 +- package.json | 2 + routes.ts | 2 +- server/api/api/v1/statuses/index.ts | 45 ++- server/api/objects/note/[uuid]/index.ts | 83 +++++ server/api/users/[uuid]/inbox/index.ts | 449 ++++++------------------ server/api/users/[uuid]/inbox/index3.ts | 403 +++++++++++++++++++++ server/api/users/[uuid]/index.ts | 5 +- utils/content_types.ts | 57 ++- 11 files changed, 788 insertions(+), 411 deletions(-) create mode 100644 server/api/objects/note/[uuid]/index.ts create mode 100644 server/api/users/[uuid]/inbox/index3.ts diff --git a/bun.lockb b/bun.lockb index 4e044f58ebe3680de09e4c2c36ead93b49443b21..d70cd3853134b18ce7266b5f61b9d1419fc1800f 100755 GIT binary patch delta 104681 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 delta 104929 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 diff --git a/database/entities/Status.ts b/database/entities/Status.ts index 293cd2d2..bf4c5548 100644 --- a/database/entities/Status.ts +++ b/database/entities/Status.ts @@ -59,8 +59,7 @@ export const isViewableByUser = (status: Status, user: User | null) => { export const fetchFromRemote = async (uri: string): Promise => { // Check if already in database - - const existingStatus: StatusWithRelations | null = + /* const existingStatus: StatusWithRelations | null = await client.status.findFirst({ where: { uri: uri, @@ -112,7 +111,7 @@ export const fetchFromRemote = async (uri: string): Promise => { } : undefined, quote: quotingStatus || undefined, - }); + }); */ }; /** @@ -192,12 +191,127 @@ export const getDescendants = async ( return viewableDescendants; }; +/** + * Get people mentioned in the content (match @username or @username@domain.com mentions) + * @param text The text to parse mentions from. + * @returns An array of users mentioned in the text. + */ +export const parseTextMentions = async (text: string) => { + const mentionedPeople = + text.match(/@[a-zA-Z0-9_]+(@[a-zA-Z0-9_]+)?/g) ?? []; + + return await client.user.findMany({ + where: { + OR: mentionedPeople.map((person) => ({ + username: person.split("@")[1], + instance: { + base_url: person.split("@")[2], + }, + })), + }, + include: userRelations, + }); +}; + +export const createNewStatus = async ( + author: User, + content: Lysand.ContentFormat, + visibility: APIStatus["visibility"], + is_sensitive: boolean, + spoiler_text: string, + emojis: Emoji[], + uri?: string, + mentions?: UserWithRelations[], + /** List of IDs of database Attachment objects */ + media_attachments?: string[], + inReplyTo?: StatusWithRelations, + quoting?: StatusWithRelations, +) => { + let htmlContent: string; + + if (content["text/html"]) { + htmlContent = content["text/html"].content; + } else if (content["text/markdown"]) { + htmlContent = linkifyHtml( + await sanitizeHtml(await parse(content["text/markdown"].content)), + ); + } else if (content["text/plain"]) { + htmlContent = linkifyStr(content["text/plain"].content); + + // Split by newline and add

tags + htmlContent = htmlContent + .split("\n") + .map((line) => `

${line}

`) + .join("\n"); + } else { + htmlContent = ""; + } + + // Parse emojis and fuse with existing emojis + let foundEmojis = emojis; + + if (author.instanceId === null) { + const parsedEmojis = await parseEmojis(htmlContent); + // Fuse and deduplicate + foundEmojis = [...emojis, ...parsedEmojis].filter( + (emoji, index, self) => + index === self.findIndex((t) => t.id === emoji.id), + ); + } + + const status = await client.status.create({ + data: { + authorId: author.id, + content: htmlContent, + contentSource: + content["text/plain"]?.content || + content["text/markdown"]?.content || + "", + contentType: "text/html", + visibility: visibility, + sensitive: is_sensitive, + spoilerText: spoiler_text, + isReblog: false, // DEPRECATED FIELD + emojis: { + connect: foundEmojis.map((emoji) => { + return { + id: emoji.id, + }; + }), + }, + attachments: media_attachments + ? { + connect: media_attachments.map((attachment) => { + return { + id: attachment, + }; + }), + } + : undefined, + inReplyToPostId: inReplyTo?.id, + quotingPostId: quoting?.id, + instanceId: author.instanceId || undefined, + uri: uri || null, + mentions: { + connect: mentions?.map((mention) => { + return { + id: mention.id, + }; + }), + }, + }, + include: statusAndUserRelations, + }); + + return status; +}; + /** * Creates a new status and saves it to the database. * @param data The data for the new status. * @returns A promise that resolves with the new status. */ -export const createNewStatus = async (data: { +export const createNewStatus2 = async (data: { account: User; application: Application | null; content: string; @@ -539,11 +653,18 @@ export const statusToLysand = (status: StatusWithRelations): Lysand.Note => { type: "Note", created_at: new Date(status.createdAt).toISOString(), id: status.id, - author: status.authorId, - uri: new URL( - `/objects/note/${status.id}`, - config.http.base_url, - ).toString(), + author: + status.author.uri || + new URL( + `/users/${status.author.id}`, + config.http.base_url, + ).toString(), + uri: + status.uri || + new URL( + `/objects/note/${status.id}`, + config.http.base_url, + ).toString(), content: { "text/html": { content: status.content, diff --git a/database/entities/User.ts b/database/entities/User.ts index 48ab3a62..0af0cb5b 100644 --- a/database/entities/User.ts +++ b/database/entities/User.ts @@ -11,6 +11,7 @@ import { addEmojiIfNotExists, emojiToAPI, emojiToLysand } from "./Emoji"; import { addInstanceIfNotExists } from "./Instance"; import { userRelations } from "./relations"; import { createNewRelationship } from "./Relationship"; +import { urlToContentFormat } from "@content_types"; export interface AuthData { user: UserWithRelations | null; @@ -493,18 +494,9 @@ export const userToLysand = (user: UserWithRelations): Lysand.User => { ).toString(), indexable: false, username: user.username, - avatar: { - [user.avatar.split(".")[1]]: { - content: getAvatarUrl(user, config), - }, - }, - header: { - [user.header.split(".")[1]]: { - content: getHeaderUrl(user, config), - }, - }, + avatar: urlToContentFormat(getAvatarUrl(user, config)) ?? undefined, + header: urlToContentFormat(getHeaderUrl(user, config)) ?? undefined, display_name: user.displayName, - fields: (user.source as APISource).fields.map((field) => ({ key: { "text/html": { diff --git a/package.json b/package.json index 402003f6..c2f1b830 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "@types/html-to-text": "^9.0.4", "@types/ioredis": "^5.0.0", "@types/jsonld": "^1.5.13", + "@types/mime-types": "^2.1.4", "@typescript-eslint/eslint-plugin": "latest", "@unocss/cli": "latest", "@unocss/transformer-directives": "^0.59.0", @@ -119,6 +120,7 @@ "megalodon": "^10.0.0", "meilisearch": "latest", "merge-deep-ts": "^1.2.6", + "mime-types": "^2.1.35", "next-route-matcher": "^1.0.1", "oauth4webapi": "^2.4.0", "prisma": "^5.6.0", diff --git a/routes.ts b/routes.ts index e2b1fece..67d4a75c 100644 --- a/routes.ts +++ b/routes.ts @@ -83,7 +83,7 @@ export const rawRoutes = { "./server/api/api/v1/statuses/[id]/unreblog", "/media/[id]": "./server/api/media/[id]/index", "/oauth/callback/[issuer]": "./server/api/oauth/callback/[issuer]/index", - "/object/[uuid]": "./server/api/object/[uuid]/index", + "/objects/note/[uuid]": "./server/api/objects/note/[uuid]/index", "/users/[uuid]": "./server/api/users/[uuid]/index", "/users/[uuid]/inbox": "./server/api/users/[uuid]/inbox/index", "/users/[uuid]/outbox": "./server/api/users/[uuid]/outbox/index", diff --git a/server/api/api/v1/statuses/index.ts b/server/api/api/v1/statuses/index.ts index c8db40e9..de554010 100644 --- a/server/api/api/v1/statuses/index.ts +++ b/server/api/api/v1/statuses/index.ts @@ -8,6 +8,7 @@ import type { StatusWithRelations } from "~database/entities/Status"; import { createNewStatus, statusToAPI } from "~database/entities/Status"; import type { UserWithRelations } from "~database/entities/User"; import { statusAndUserRelations } from "~database/entities/relations"; +import type { APIStatus } from "~types/entities/status"; export const meta = applyConfig({ allowedMethods: ["POST"], @@ -211,30 +212,26 @@ export default apiRoute<{ return errorResponse("Invalid media IDs", 422); } - const newStatus = await createNewStatus({ - account: user, - application, - content: sanitizedStatus, - visibility: - visibility || - (config.defaults.visibility as - | "public" - | "unlisted" - | "private" - | "direct"), - sensitive: sensitive || false, - spoiler_text: spoiler_text || "", - emojis: [], - media_attachments: media_ids, - reply: - replyStatus && replyUser - ? { - user: replyUser, - status: replyStatus, - } - : undefined, - quote: quote || undefined, - }); + const newStatus = await createNewStatus( + user, + { + "text/html": { + content: sanitizedStatus, + }, + [content_type ?? "text/plain"]: { + content: status ?? "", + }, + }, + visibility as APIStatus["visibility"], + sensitive ?? false, + spoiler_text ?? "", + [], + undefined, + [], + media_ids, + replyStatus ?? undefined, + quote ?? undefined, + ); // TODO: add database jobs to deliver the post diff --git a/server/api/objects/note/[uuid]/index.ts b/server/api/objects/note/[uuid]/index.ts new file mode 100644 index 00000000..2e6742b2 --- /dev/null +++ b/server/api/objects/note/[uuid]/index.ts @@ -0,0 +1,83 @@ +import { apiRoute, applyConfig } from "@api"; +import { errorResponse, jsonResponse } from "@response"; +import { client } from "~database/datasource"; +import { userToLysand } from "~database/entities/User"; +import { statusAndUserRelations } from "~database/entities/relations"; +import type * as Lysand from "lysand-types"; +import { statusToLysand } from "~database/entities/Status"; + +export const meta = applyConfig({ + allowedMethods: ["GET"], + auth: { + required: false, + }, + ratelimits: { + duration: 60, + max: 500, + }, + route: "/objects/note/:uuid", +}); + +export default apiRoute(async (req, matchedRoute, extraData) => { + const uuid = matchedRoute.params.uuid; + + const status = await client.status.findUnique({ + where: { + id: uuid, + }, + include: statusAndUserRelations, + }); + + if (!status) { + return errorResponse("Note not found", 404); + } + + const config = await extraData.configManager.getConfig(); + + const output = statusToLysand(status); + + const privateKey = await crypto.subtle.importKey( + "pkcs8", + Uint8Array.from(atob(status.author.privateKey ?? ""), (c) => + c.charCodeAt(0), + ), + "Ed25519", + false, + ["sign"], + ); + + const digest = await crypto.subtle.digest( + "SHA-256", + new TextEncoder().encode(JSON.stringify(output)), + ); + + const userInbox = new URL( + "http://lysand.localhost:8080/users/018ec11c-c6cb-7a67-bd20-a4c81bf42912/inbox", + ); + + const date = new Date(); + + const signature = await crypto.subtle.sign( + "Ed25519", + privateKey, + new TextEncoder().encode( + `(request-target): post ${userInbox.pathname}\n` + + `host: ${userInbox.host}\n` + + `date: ${date.toISOString()}\n` + + `digest: SHA-256=${btoa( + String.fromCharCode(...new Uint8Array(digest)), + )}\n`, + ), + ); + + const signatureBase64 = btoa( + String.fromCharCode(...new Uint8Array(signature)), + ); + + return jsonResponse({ + Date: date.toISOString(), + Origin: "example.com", + Signature: `keyId="https://example.com/users/${status.author.id}",algorithm="ed25519",headers="(request-target) host date digest",signature="${signatureBase64}"`, + post: output, + }); +}); diff --git a/server/api/users/[uuid]/inbox/index.ts b/server/api/users/[uuid]/inbox/index.ts index a1a98e25..df5d7f3e 100644 --- a/server/api/users/[uuid]/inbox/index.ts +++ b/server/api/users/[uuid]/inbox/index.ts @@ -1,25 +1,10 @@ -// TODO: Refactor into smaller packages import { apiRoute, applyConfig } from "@api"; -import { getBestContentType } from "@content_types"; -import { errorResponse, jsonResponse } from "@response"; +import { errorResponse, response } from "@response"; import { client } from "~database/datasource"; -import { parseEmojis } from "~database/entities/Emoji"; -import { createLike, deleteLike } from "~database/entities/Like"; -import { createFromObject } from "~database/entities/Object"; -import { createNewStatus, fetchFromRemote } from "~database/entities/Status"; -import { parseMentionsUris } from "~database/entities/User"; -import { - statusAndUserRelations, - userRelations, -} from "~database/entities/relations"; -import type { - Announce, - Like, - LysandAction, - LysandPublication, - Patch, - Undo, -} from "~types/lysand/Object"; +import { userRelations } from "~database/entities/relations"; +import type * as Lysand from "lysand-types"; +import { createNewStatus } from "~database/entities/Status"; +import type { APIStatus } from "~types/entities/status"; export const meta = applyConfig({ allowedMethods: ["POST"], @@ -30,73 +15,48 @@ export const meta = applyConfig({ duration: 60, max: 500, }, - route: "/users/:username/inbox", + route: "/users/:uuid", }); -/** - * ActivityPub user inbox endpoint - */ export default apiRoute(async (req, matchedRoute, extraData) => { - const username = matchedRoute.params.username; + const uuid = matchedRoute.params.uuid; - const config = await extraData.configManager.getConfig(); - - /* try { - if ( - config.activitypub.reject_activities.includes( - new URL(req.headers.get("Origin") ?? "").hostname, - ) - ) { - // Discard request - return jsonResponse({}); - } - } catch (e) { - console.error( - `[-] Error parsing Origin header of incoming Activity from ${req.headers.get( - "Origin", - )}`, - ); - console.error(e); - } */ - - // Process request body - const body = (await req.json()) as LysandPublication | LysandAction; - - const author = await client.user.findUnique({ + const user = await client.user.findUnique({ where: { - username, + id: uuid, }, include: userRelations, }); - if (!author) { - // TODO: Add new author to database - return errorResponse("Author not found", 404); + if (!user) { + return errorResponse("User not found", 404); } - // Verify HTTP signature - /* if (config.activitypub.authorized_fetch) { - // Check if date is older than 30 seconds - const origin = req.headers.get("Origin"); + const config = await extraData.configManager.getConfig(); - if (!origin) { - return errorResponse("Origin header is required", 401); - } + // Process incoming request + const body = extraData.parsedRequest as Lysand.Entity; - const date = req.headers.get("Date"); - - if (!date) { - return errorResponse("Date header is required", 401); - } - - if (new Date(date).getTime() < Date.now() - 30000) { - return errorResponse("Date is too old (max 30 seconds)", 401); - } + // Verify request signature + // TODO: Check if instance is defederated + // biome-ignore lint/correctness/noConstantCondition: Temporary + if (true) { + // request is a Request object containing the previous request const signatureHeader = req.headers.get("Signature"); + const origin = req.headers.get("Origin"); + const date = req.headers.get("Date"); if (!signatureHeader) { - return errorResponse("Signature header is required", 401); + return errorResponse("Missing Signature header", 400); + } + + if (!origin) { + return errorResponse("Missing Origin header", 400); + } + + if (!date) { + return errorResponse("Missing Date header", 400); } const signature = signatureHeader @@ -105,297 +65,98 @@ export default apiRoute(async (req, matchedRoute, extraData) => { const digest = await crypto.subtle.digest( "SHA-256", - new TextEncoder().encode(await req.text()), + new TextEncoder().encode(JSON.stringify(body)), ); - const expectedSignedString = - `(request-target): ${req.method.toLowerCase()} ${req.url}\n` + - `host: ${req.url}\n` + - `date: ${date}\n` + - `digest: SHA-256=${Buffer.from(digest).toString("base64")}`; + const keyId = signatureHeader + .split("keyId=")[1] + .split(",")[0] + .replace(/"/g, ""); - // author.public_key is base64 encoded raw public key - const publicKey = await crypto.subtle.importKey( + // TODO: Fetch sender using WebFinger if not found + const sender = await client.user.findUnique({ + where: { + uri: keyId, + }, + }); + + if (!sender) { + return errorResponse("Invalid keyId", 400); + } + + const public_key = await crypto.subtle.importKey( "spki", - Buffer.from(author.publicKey, "base64"), + Uint8Array.from(atob(sender.publicKey), (c) => c.charCodeAt(0)), "Ed25519", false, ["verify"], ); + const expectedSignedString = + `(request-target): ${req.method.toLowerCase()} ${ + new URL(req.url).pathname + }\n` + + `host: ${new URL(req.url).host}\n` + + `date: ${date}\n` + + `digest: SHA-256=${btoa( + String.fromCharCode(...new Uint8Array(digest)), + )}\n`; + // Check if signed string is valid const isValid = await crypto.subtle.verify( "Ed25519", - publicKey, - Buffer.from(signature, "base64"), + public_key, + Uint8Array.from(atob(signature), (c) => c.charCodeAt(0)), new TextEncoder().encode(expectedSignedString), ); if (!isValid) { - return errorResponse("Invalid signature", 401); - } - } */ - - // Get the object's ActivityPub type - const type = body.type; - - switch (type) { - case "Note": { - // Store the object in the LysandObject table - await createFromObject(body); - - const content = getBestContentType(body.contents); - - const emojis = await parseEmojis(content?.content || ""); - - const newStatus = await createNewStatus({ - account: author, - content: content?.content || "", - content_type: content?.content_type, - application: null, - // TODO: Add visibility - visibility: "public", - spoiler_text: body.subject || "", - sensitive: body.is_sensitive, - uri: body.uri, - emojis: emojis, - mentions: await parseMentionsUris(body.mentions), - }); - - // If there is a reply, fetch all the reply parents and add them to the database - if (body.replies_to.length > 0) { - newStatus.inReplyToPostId = - (await fetchFromRemote(body.replies_to[0]))?.id || null; - } - - // Same for quotes - if (body.quotes.length > 0) { - newStatus.quotingPostId = - (await fetchFromRemote(body.quotes[0]))?.id || null; - } - - await client.status.update({ - where: { - id: newStatus.id, - }, - data: { - inReplyToPostId: newStatus.inReplyToPostId, - quotingPostId: newStatus.quotingPostId, - }, - }); - - break; - } - case "Patch": { - const patch = body as Patch; - // Store the object in the LysandObject table - await createFromObject(patch); - - // Edit the status - - const content = getBestContentType(patch.contents); - - const emojis = await parseEmojis(content?.content || ""); - - const status = await client.status.findUnique({ - where: { - uri: patch.patched_id, - }, - include: statusAndUserRelations, - }); - - if (!status) { - return errorResponse("Status not found", 404); - } - - status.content = content?.content || ""; - status.contentType = content?.content_type || "text/plain"; - status.spoilerText = patch.subject || ""; - status.sensitive = patch.is_sensitive; - status.emojis = emojis; - - // If there is a reply, fetch all the reply parents and add them to the database - if (body.replies_to.length > 0) { - status.inReplyToPostId = - (await fetchFromRemote(body.replies_to[0]))?.id || null; - } - - // Same for quotes - if (body.quotes.length > 0) { - status.quotingPostId = - (await fetchFromRemote(body.quotes[0]))?.id || null; - } - - await client.status.update({ - where: { - id: status.id, - }, - data: { - content: status.content, - contentType: status.contentType, - spoilerText: status.spoilerText, - sensitive: status.sensitive, - emojis: { - connect: status.emojis.map((emoji) => ({ - id: emoji.id, - })), - }, - inReplyToPostId: status.inReplyToPostId, - quotingPostId: status.quotingPostId, - }, - }); - break; - } - case "Like": { - const like = body as Like; - // Store the object in the LysandObject table - await createFromObject(body); - - const likedStatus = await client.status.findUnique({ - where: { - uri: like.object, - }, - include: statusAndUserRelations, - }); - - if (!likedStatus) { - return errorResponse("Status not found", 404); - } - - await createLike(author, likedStatus); - - break; - } - case "Dislike": { - // Store the object in the LysandObject table - await createFromObject(body); - - return jsonResponse({ - info: "Dislikes are not supported by this software", - }); - } - case "Follow": { - // Store the object in the LysandObject table - await createFromObject(body); - break; - } - case "FollowAccept": { - // Store the object in the LysandObject table - await createFromObject(body); - break; - } - case "FollowReject": { - // Store the object in the LysandObject table - await createFromObject(body); - break; - } - case "Announce": { - const announce = body as Announce; - // Store the object in the LysandObject table - await createFromObject(body); - - const rebloggedStatus = await client.status.findUnique({ - where: { - uri: announce.object, - }, - include: statusAndUserRelations, - }); - - if (!rebloggedStatus) { - return errorResponse("Status not found", 404); - } - - // Create new reblog - await client.status.create({ - data: { - authorId: author.id, - reblogId: rebloggedStatus.id, - isReblog: true, - uri: body.uri, - visibility: rebloggedStatus.visibility, - sensitive: false, - }, - include: statusAndUserRelations, - }); - - // Create notification - await client.notification.create({ - data: { - accountId: author.id, - notifiedId: rebloggedStatus.authorId, - type: "reblog", - statusId: rebloggedStatus.id, - }, - }); - break; - } - case "Undo": { - const undo = body as Undo; - // Store the object in the LysandObject table - await createFromObject(body); - - const object = await client.lysandObject.findUnique({ - where: { - uri: undo.object, - }, - }); - - if (!object) { - return errorResponse("Object not found", 404); - } - - switch (object.type) { - case "Like": { - const status = await client.status.findUnique({ - where: { - uri: undo.object, - authorId: author.id, - }, - include: statusAndUserRelations, - }); - - if (!status) { - return errorResponse("Status not found", 404); - } - - await deleteLike(author, status); - break; - } - case "Announce": { - await client.status.delete({ - where: { - uri: undo.object, - authorId: author.id, - }, - include: statusAndUserRelations, - }); - break; - } - case "Note": { - await client.status.delete({ - where: { - uri: undo.object, - authorId: author.id, - }, - include: statusAndUserRelations, - }); - break; - } - default: { - return errorResponse("Invalid object type", 400); - } - } - break; - } - case "Extension": { - // Store the object in the LysandObject table - await createFromObject(body); - break; - } - default: { - return errorResponse("Invalid type", 400); + return errorResponse("Invalid signature", 400); } } - return jsonResponse({}); + // Add sent data to database + switch (body.type) { + case "Note": { + const note = body as Lysand.Note; + + const account = await client.user.findUnique({ + where: { + uri: note.author, + }, + }); + + if (!account) { + return errorResponse("Author not found", 400); + } + + await createNewStatus( + account, + note.content ?? { + "text/plain": { + content: "", + }, + }, + note.visibility as APIStatus["visibility"], + note.is_sensitive ?? false, + note.subject ?? "", + [], + note.uri, + // TODO: Resolve mention,s + [], + // TODO: Add attachments + [], + // TODO: Resolve replies and quoting + undefined, + undefined, + ); + + return response("Note created", 201); + } + default: { + return errorResponse("Unknown object type", 400); + } + } + + //return jsonResponse(userToLysand(user)); }); diff --git a/server/api/users/[uuid]/inbox/index3.ts b/server/api/users/[uuid]/inbox/index3.ts new file mode 100644 index 00000000..90531ac9 --- /dev/null +++ b/server/api/users/[uuid]/inbox/index3.ts @@ -0,0 +1,403 @@ +// TODO: Refactor into smaller packages +import { apiRoute, applyConfig } from "@api"; +import { getBestContentType } from "@content_types"; +import { errorResponse, jsonResponse } from "@response"; +import { client } from "~database/datasource"; +import { parseEmojis } from "~database/entities/Emoji"; +import { createLike, deleteLike } from "~database/entities/Like"; +import { createFromObject } from "~database/entities/Object"; +import { createNewStatus, fetchFromRemote } from "~database/entities/Status"; +import { parseMentionsUris } from "~database/entities/User"; +import { + statusAndUserRelations, + userRelations, +} from "~database/entities/relations"; +import type { + Announce, + Like, + LysandAction, + LysandPublication, + Patch, + Undo, +} from "~types/lysand/Object"; + +export const meta = applyConfig({ + allowedMethods: ["POST"], + auth: { + required: false, + }, + ratelimits: { + duration: 60, + max: 500, + }, + route: "/users/:uuid/inbox", +}); + +/** + * ActivityPub user inbox endpoint + */ +export default apiRoute(async (req, matchedRoute, extraData) => { + const username = matchedRoute.params.username; + + const config = await extraData.configManager.getConfig(); + + /* try { + if ( + config.activitypub.reject_activities.includes( + new URL(req.headers.get("Origin") ?? "").hostname, + ) + ) { + // Discard request + return jsonResponse({}); + } + } catch (e) { + console.error( + `[-] Error parsing Origin header of incoming Activity from ${req.headers.get( + "Origin", + )}`, + ); + console.error(e); + } */ + + // Process request body + const body = (await req.json()) as LysandPublication | LysandAction; + + const author = await client.user.findUnique({ + where: { + username, + }, + include: userRelations, + }); + + if (!author) { + // TODO: Add new author to database + return errorResponse("Author not found", 404); + } + + // Verify HTTP signature + /* if (config.activitypub.authorized_fetch) { + // Check if date is older than 30 seconds + const origin = req.headers.get("Origin"); + + if (!origin) { + return errorResponse("Origin header is required", 401); + } + + const date = req.headers.get("Date"); + + if (!date) { + return errorResponse("Date header is required", 401); + } + + if (new Date(date).getTime() < Date.now() - 30000) { + return errorResponse("Date is too old (max 30 seconds)", 401); + } + + const signatureHeader = req.headers.get("Signature"); + + if (!signatureHeader) { + return errorResponse("Signature header is required", 401); + } + + const signature = signatureHeader + .split("signature=")[1] + .replace(/"/g, ""); + + const digest = await crypto.subtle.digest( + "SHA-256", + new TextEncoder().encode(await req.text()), + ); + + const expectedSignedString = + `(request-target): ${req.method.toLowerCase()} ${req.url}\n` + + `host: ${req.url}\n` + + `date: ${date}\n` + + `digest: SHA-256=${Buffer.from(digest).toString("base64")}`; + + // author.public_key is base64 encoded raw public key + const publicKey = await crypto.subtle.importKey( + "spki", + Buffer.from(author.publicKey, "base64"), + "Ed25519", + false, + ["verify"], + ); + + // Check if signed string is valid + const isValid = await crypto.subtle.verify( + "Ed25519", + publicKey, + Buffer.from(signature, "base64"), + new TextEncoder().encode(expectedSignedString), + ); + + if (!isValid) { + return errorResponse("Invalid signature", 401); + } + } */ + + // Get the object's ActivityPub type + const type = body.type; + + switch (type) { + case "Note": { + // Store the object in the LysandObject table + await createFromObject(body); + + const content = getBestContentType(body.contents); + + const emojis = await parseEmojis(content?.content || ""); + + const newStatus = await createNewStatus(author); + + const newStatus = await createNewStatus({ + account: author, + content: content?.content || "", + content_type: content?.content_type, + application: null, + // TODO: Add visibility + visibility: "public", + spoiler_text: body.subject || "", + sensitive: body.is_sensitive, + uri: body.uri, + emojis: emojis, + mentions: await parseMentionsUris(body.mentions), + }); + + // If there is a reply, fetch all the reply parents and add them to the database + if (body.replies_to.length > 0) { + newStatus.inReplyToPostId = + (await fetchFromRemote(body.replies_to[0]))?.id || null; + } + + // Same for quotes + if (body.quotes.length > 0) { + newStatus.quotingPostId = + (await fetchFromRemote(body.quotes[0]))?.id || null; + } + + await client.status.update({ + where: { + id: newStatus.id, + }, + data: { + inReplyToPostId: newStatus.inReplyToPostId, + quotingPostId: newStatus.quotingPostId, + }, + }); + + break; + } + case "Patch": { + const patch = body as Patch; + // Store the object in the LysandObject table + await createFromObject(patch); + + // Edit the status + + const content = getBestContentType(patch.contents); + + const emojis = await parseEmojis(content?.content || ""); + + const status = await client.status.findUnique({ + where: { + uri: patch.patched_id, + }, + include: statusAndUserRelations, + }); + + if (!status) { + return errorResponse("Status not found", 404); + } + + status.content = content?.content || ""; + status.contentType = content?.content_type || "text/plain"; + status.spoilerText = patch.subject || ""; + status.sensitive = patch.is_sensitive; + status.emojis = emojis; + + // If there is a reply, fetch all the reply parents and add them to the database + if (body.replies_to.length > 0) { + status.inReplyToPostId = + (await fetchFromRemote(body.replies_to[0]))?.id || null; + } + + // Same for quotes + if (body.quotes.length > 0) { + status.quotingPostId = + (await fetchFromRemote(body.quotes[0]))?.id || null; + } + + await client.status.update({ + where: { + id: status.id, + }, + data: { + content: status.content, + contentType: status.contentType, + spoilerText: status.spoilerText, + sensitive: status.sensitive, + emojis: { + connect: status.emojis.map((emoji) => ({ + id: emoji.id, + })), + }, + inReplyToPostId: status.inReplyToPostId, + quotingPostId: status.quotingPostId, + }, + }); + break; + } + case "Like": { + const like = body as Like; + // Store the object in the LysandObject table + await createFromObject(body); + + const likedStatus = await client.status.findUnique({ + where: { + uri: like.object, + }, + include: statusAndUserRelations, + }); + + if (!likedStatus) { + return errorResponse("Status not found", 404); + } + + await createLike(author, likedStatus); + + break; + } + case "Dislike": { + // Store the object in the LysandObject table + await createFromObject(body); + + return jsonResponse({ + info: "Dislikes are not supported by this software", + }); + } + case "Follow": { + // Store the object in the LysandObject table + await createFromObject(body); + break; + } + case "FollowAccept": { + // Store the object in the LysandObject table + await createFromObject(body); + break; + } + case "FollowReject": { + // Store the object in the LysandObject table + await createFromObject(body); + break; + } + case "Announce": { + const announce = body as Announce; + // Store the object in the LysandObject table + await createFromObject(body); + + const rebloggedStatus = await client.status.findUnique({ + where: { + uri: announce.object, + }, + include: statusAndUserRelations, + }); + + if (!rebloggedStatus) { + return errorResponse("Status not found", 404); + } + + // Create new reblog + await client.status.create({ + data: { + authorId: author.id, + reblogId: rebloggedStatus.id, + isReblog: true, + uri: body.uri, + visibility: rebloggedStatus.visibility, + sensitive: false, + }, + include: statusAndUserRelations, + }); + + // Create notification + await client.notification.create({ + data: { + accountId: author.id, + notifiedId: rebloggedStatus.authorId, + type: "reblog", + statusId: rebloggedStatus.id, + }, + }); + break; + } + case "Undo": { + const undo = body as Undo; + // Store the object in the LysandObject table + await createFromObject(body); + + const object = await client.lysandObject.findUnique({ + where: { + uri: undo.object, + }, + }); + + if (!object) { + return errorResponse("Object not found", 404); + } + + switch (object.type) { + case "Like": { + const status = await client.status.findUnique({ + where: { + uri: undo.object, + authorId: author.id, + }, + include: statusAndUserRelations, + }); + + if (!status) { + return errorResponse("Status not found", 404); + } + + await deleteLike(author, status); + break; + } + case "Announce": { + await client.status.delete({ + where: { + uri: undo.object, + authorId: author.id, + }, + include: statusAndUserRelations, + }); + break; + } + case "Note": { + await client.status.delete({ + where: { + uri: undo.object, + authorId: author.id, + }, + include: statusAndUserRelations, + }); + break; + } + default: { + return errorResponse("Invalid object type", 400); + } + } + break; + } + case "Extension": { + // Store the object in the LysandObject table + await createFromObject(body); + break; + } + default: { + return errorResponse("Invalid type", 400); + } + } + + return jsonResponse({}); +}); diff --git a/server/api/users/[uuid]/index.ts b/server/api/users/[uuid]/index.ts index 6466b00f..91898470 100644 --- a/server/api/users/[uuid]/index.ts +++ b/server/api/users/[uuid]/index.ts @@ -5,7 +5,7 @@ import { userToLysand } from "~database/entities/User"; import { userRelations } from "~database/entities/relations"; export const meta = applyConfig({ - allowedMethods: ["POST"], + allowedMethods: ["GET"], auth: { required: false, }, @@ -16,9 +16,6 @@ export const meta = applyConfig({ route: "/users/:uuid", }); -/** - * ActivityPub user inbox endpoint - */ export default apiRoute(async (req, matchedRoute) => { const uuid = matchedRoute.params.uuid; diff --git a/utils/content_types.ts b/utils/content_types.ts index 71c929d9..468e2ff3 100644 --- a/utils/content_types.ts +++ b/utils/content_types.ts @@ -1,21 +1,42 @@ -import type { ContentFormat } from "~types/lysand/Object"; +import type * as Lysand from "lysand-types"; +import { lookup } from "mime-types"; -export const getBestContentType = (contents: ContentFormat[]) => { - // Find the best content and content type - if (contents.find((c) => c.content_type === "text/x.misskeymarkdown")) { - return ( - contents.find((c) => c.content_type === "text/x.misskeymarkdown") || - null - ); +export const getBestContentType = (content?: Lysand.ContentFormat) => { + if (!content) return { content: "", format: "text/plain" }; + + const bestFormatsRanked = [ + "text/x.misskeymarkdown", + "text/html", + "text/markdown", + "text/plain", + ]; + + for (const format of bestFormatsRanked) { + if (content[format]) + return { content: content[format].content, format }; } - if (contents.find((c) => c.content_type === "text/html")) { - return contents.find((c) => c.content_type === "text/html") || null; - } - if (contents.find((c) => c.content_type === "text/markdown")) { - return contents.find((c) => c.content_type === "text/markdown") || null; - } - if (contents.find((c) => c.content_type === "text/plain")) { - return contents.find((c) => c.content_type === "text/plain") || null; - } - return contents[0] || null; + + return { content: "", format: "text/plain" }; +}; + +export const urlToContentFormat = ( + url: string, +): Lysand.ContentFormat | null => { + if (!url) return null; + if (url.startsWith("https://api.dicebear.com/")) { + return { + "image/svg+xml": { + content: url, + }, + }; + } + const mimeType = + lookup(url.replace(new URL(url).search, "")) || + "application/octet-stream"; + + return { + [mimeType]: { + content: url, + }, + }; };