From 4ffa9626f3baa51591e80e862e27a6f1572f7707 Mon Sep 17 00:00:00 2001 From: Moon Man Date: Mon, 1 Jan 2024 07:52:40 -0500 Subject: [PATCH] actor type on user, lookup table --- migrations/20240101055331_lookup.js | 72 +++++++++++++++++++++++++++++ src/activity.ts | 8 ++-- src/user.ts | 1 + 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 migrations/20240101055331_lookup.js diff --git a/migrations/20240101055331_lookup.js b/migrations/20240101055331_lookup.js new file mode 100644 index 0000000..1e3d2bb --- /dev/null +++ b/migrations/20240101055331_lookup.js @@ -0,0 +1,72 @@ +import { generateKeyPair } from "node:crypto"; + +const SITE_USER_ID = 1_000_000_000; + +/** + * Add a lookup table. + * Add an actor type to "users" table. + */ + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +export const up = async (knex) => { + return knex.schema + .createTable("lookup", (table) => { + table.string("key").primary(); + table.string("value"); + }) + .then(async () => { + await knex.schema.table("users", (table) => { + table.string("actor_type"); + }); + + const { pub, priv } = await (new Promise((resolve, reject) => { + generateKeyPair("rsa", { + modulusLength: 2048, + publicKeyEncoding: { + type: "spki", + format: "pem" + }, + privateKeyEncoding: { + type: "pkcs8", + format: "pem" + } + }, (err, pub, priv) => { + if (err) reject(err); + else resolve({ pub, priv }); + }); + })); + + await knex("users").insert({ + id: SITE_USER_ID, + actor_type: "Application", + name: "site", + nickname: process.env.blog_host, + bio: "The site itself.", + public_key: pub, + private_key: priv, + deleted: false + }); + }); + ; +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +export const down = async (knex) => { + await knex("users") + .delete() + .where("id", SITE_USER_ID) + ; + + return knex.schema + .dropTableIfExists("lookup") + .table("users", (table) => { + table.dropColumn("actor_type"); + }); + ; +}; diff --git a/src/activity.ts b/src/activity.ts index b14bc4c..9cec981 100644 --- a/src/activity.ts +++ b/src/activity.ts @@ -5,7 +5,7 @@ import { User, getByActor } from "./user.js"; import { fillRoute, reverseRoute } from "./router.js"; import { streamToString, hashDigest } from "./util.js"; import { signedFetch, SignedInit, getActor } from "./net.js"; -import { getById as getUserById, getKeyId } from "./user.js"; +import { getById as getUserById, keyIdFromNickname } from "./user.js"; import parser from "activitypub-http-signatures"; import type { Request, Response } from "express"; import { addFollower } from "./follower.js"; @@ -60,7 +60,7 @@ export const handleInboxPost = async (req: Request, res: Response) => { console.log("found article author"); const init: SignedInit = { - keyId: getKeyId(user.nickname), + keyId: keyIdFromNickname(user.nickname), privateKey: user.private_key }; @@ -98,7 +98,7 @@ export const handleInboxPost = async (req: Request, res: Response) => { } const init: SignedInit = { - keyId: getKeyId(signer.nickname), + keyId: keyIdFromNickname(signer.nickname), privateKey: signer.private_key }; @@ -271,7 +271,7 @@ export const sendAccept = async (user: User, followId: string, follower: string, console.log("Accept payload:", payload); const init: RequestInit = { method: "POST", body: payload }; - const init2 = { privateKey: user.private_key, keyId: getKeyId(user.nickname) }; + const init2 = { privateKey: user.private_key, keyId: keyIdFromNickname(user.nickname) }; const result = await signedFetch(inbox, init, init2); console.log("response status:", result.status); diff --git a/src/user.ts b/src/user.ts index 1caee49..db37a0e 100644 --- a/src/user.ts +++ b/src/user.ts @@ -8,6 +8,7 @@ export const nicknameRegex = /^[a-zA-Z0-9_]+$/; export const zUser = z.object({ id: z.number().min(0), + actor_type: z.string().min(1), name: z.string().min(1), nickname: z.string().regex(nicknameRegex), bio: z.string(),