diff --git a/src/pages/api/activitypub/actor.ts b/functions/api/activitypub/actor.ts similarity index 92% rename from src/pages/api/activitypub/actor.ts rename to functions/api/activitypub/actor.ts index d2e2fbd2..fcf1d504 100644 --- a/src/pages/api/activitypub/actor.ts +++ b/functions/api/activitypub/actor.ts @@ -1,6 +1,8 @@ /* eslint-disable import/prefer-default-export */ -export const GET = () => +import { Env } from './types'; + +export const onRequestGet: PagesFunction = (ctx) => new Response( JSON.stringify({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'], @@ -37,9 +39,7 @@ export const GET = () => publicKey: { id: 'https://blog.yunyi.beiyan.us/api/activitypub/actor#main-key', owner: 'https://blog.yunyi.beiyan.us/api/activitypub/actor', - publicKeyPem: `-----BEGIN PUBLIC KEY----- -MCowBQYDK2VwAyEAK32mZ6NHWvErlVDNipED0uv0WoxpHvcL2OWCQ/mCLBw= ------END PUBLIC KEY-----`, + publicKeyPem: JSON.parse(ctx.env.PUBLIC_KEY), }, }), { headers: { 'Content-Type': 'application/activity+json' } }, diff --git a/functions/api/activitypub/inbox.ts b/functions/api/activitypub/inbox.ts index 12dae850..449dd85b 100644 --- a/functions/api/activitypub/inbox.ts +++ b/functions/api/activitypub/inbox.ts @@ -3,8 +3,10 @@ import type { AP } from 'activitypub-core-types'; import { Kysely } from 'kysely'; import { D1Dialect } from 'kysely-d1'; import type { Database, Env } from './types'; +import { getPrivateKey } from '../../src/utils/getKey'; +import { signRequest } from '../../src/utils/http-signing'; -const handleFollow = async (body: AP.Follow, db: Kysely) => { +const handleFollow = async (body: AP.Follow, db: Kysely, env: Env) => { if (Array.isArray(body.actor)) throw new Error('Not Implemented'); let aid = ''; if (typeof body.actor === 'string') aid = body.actor; @@ -19,7 +21,7 @@ const handleFollow = async (body: AP.Follow, db: Kysely) => { oc.column('actorId').doUpdateSet({ inbox: info.inbox as unknown as string }), ) .execute(); - await fetch(info.inbox as unknown as string, { + const acceptReq = new Request(info.inbox as unknown as string, { method: 'post', headers: { 'Content-Type': 'application/activity+json', Accept: 'application/activity+json' }, body: JSON.stringify({ @@ -37,6 +39,13 @@ const handleFollow = async (body: AP.Follow, db: Kysely) => { }, }), }); + const privKey = await getPrivateKey(env); + await signRequest( + acceptReq, + privKey, + new URL('https://blog.yunyi.beiyan.us/api/activitypub/actor'), + ); + await fetch(acceptReq); return new Response('Ok'); }; @@ -59,7 +68,7 @@ export const onRequestPost: PagesFunction = async (ctx) => { if (!['Follow', 'Undo'].includes(body.type)) throw new Error('Not Implemented'); switch (body.type) { case 'Follow': - return handleFollow(body as AP.Follow, db); + return handleFollow(body as AP.Follow, db, ctx.env); case 'Undo': return handleUnfollow(body as AP.Undo, db); default: diff --git a/functions/api/genKeyPair/test.ts b/functions/api/genKeyPair/test.ts deleted file mode 100644 index 5da0fd30..00000000 --- a/functions/api/genKeyPair/test.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Env } from '../activitypub/types'; - -export const onRequestGet: PagesFunction = async (ctx) => { - return new Response(JSON.stringify({ pub: JSON.parse(ctx.env.PUBLIC_KEY) })); -}; diff --git a/functions/src/utils/getKey.ts b/functions/src/utils/getKey.ts new file mode 100644 index 00000000..34b60834 --- /dev/null +++ b/functions/src/utils/getKey.ts @@ -0,0 +1,6 @@ +import { Env } from '../../api/activitypub/types'; +import { importPrivKey, importPublicKey } from './key-ops'; + +export const getPublicKey = async (env: Env) => importPublicKey(JSON.parse(env.PUBLIC_KEY)); + +export const getPrivateKey = async (env: Env) => importPrivKey(JSON.parse(env.PRIV_KEY)); diff --git a/tsconfig.json b/tsconfig.json index 9b843a73..b0f6695d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,6 +17,6 @@ "@assets/*": ["src/assets/*"] } }, - "include": ["src/**/*.astro", "src/**/*.ts", "src/**/*.tsx", "uno.config.ts", "astro.config.ts"], + "include": ["src/**/*.astro", "src/**/*.ts", "src/**/*.tsx", "uno.config.ts", "astro.config.ts"] // "references": [{ "path": "./functions/tsconfig.json" }] }