Add basic ability to update activities to current running standards.

This commit is contained in:
Andrew Pietila 2024-07-29 20:50:34 -05:00
parent 14ba17c21a
commit 8eceb3fb17
9 changed files with 81 additions and 8 deletions

View file

@ -2,7 +2,7 @@ import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "sqlite",
schema: "./src/schema.ts",
schema: "./src/db/schema.ts",
out: "./drizzle",
dbCredentials: {
"url": "./brainz-social.db"

8
package-lock.json generated
View file

@ -21,6 +21,7 @@
"devDependencies": {
"@types/bcrypt": "^5.0.2",
"@types/better-sqlite3": "^7.6.11",
"@types/jsonld": "^1.5.15",
"@types/node": "^22.0.0",
"@types/prompt": "^1.1.8",
"@types/react": "^18.3.3",
@ -1380,6 +1381,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/jsonld": {
"version": "1.5.15",
"resolved": "https://registry.npmjs.org/@types/jsonld/-/jsonld-1.5.15.tgz",
"integrity": "sha512-PlAFPZjL+AuGYmwlqwKEL0IMP8M8RexH0NIPGfCVWSQ041H2rR/8OlyZSD7KsCVoN8vCfWdtWDBxX8yBVP+xow==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz",

View file

@ -23,6 +23,7 @@
"devDependencies": {
"@types/bcrypt": "^5.0.2",
"@types/better-sqlite3": "^7.6.11",
"@types/jsonld": "^1.5.15",
"@types/node": "^22.0.0",
"@types/prompt": "^1.1.8",
"@types/react": "^18.3.3",

View file

@ -1,5 +1,5 @@
import db from "@/../db/drizzle";
import {user} from "@/schema";
import db from "@/db/drizzle";
import {user} from "@/db/schema";
import { NextRequest, NextResponse } from "next/server";
export const dynamic = 'force-dynamic';

View file

@ -1,5 +1,5 @@
import { pubPrivKeys, user } from '@/schema';
import db from '../db/drizzle';
import { pubPrivKeys, user } from '@/db/schema';
import db from '@/db/drizzle';
import { start as promptStart, get as promptGet } from 'prompt';
import * as bcrypt from 'bcrypt';
@ -102,7 +102,7 @@ const main = async () => {
}
}
],
"id": `https://${result.Domain}/users/${result.Username}`,
"id": `https://${result.Domain}/api/activitypub/user/${result.Username}`,
"type": "Person",
"following": `https://${result.Domain}/users/${result.Username}/following`,
"followers": `https://${result.Domain}/users/${result.Username}/followers`,
@ -122,8 +122,8 @@ const main = async () => {
"devices": `https://${result.Domain}/users/${result.Username}/collections/devices`,
"alsoKnownAs": [],
"publicKey": {
"id": `https://${result.Domain}/users/${result.Username}#main-key`,
"owner": `https://${result.Domain}/users/${result.Username}`,
"id": `https://${result.Domain}/api/activitypub/user/${result.Username}#main-key`,
"owner": `https://${result.Domain}/api/activitypub/user/${result.Username}`,
"publicKeyPem": publicKey.toString()
},
"tag": [],

View file

@ -0,0 +1,59 @@
import db from '@/db/drizzle';
import { pubPrivKeys, user } from '@/db/schema';
import {desc, eq} from 'drizzle-orm';
import jsonld from 'jsonld';
import {get as promptGet, start as promptStart} from 'prompt';
import { generateKeyPair as generateKeyPairCallback } from 'crypto';
import { promisify } from 'util';
const generateKeyPair = promisify(generateKeyPairCallback);
async function main() {
const rows = await db.select({id: user.id, activity: user.activity, name: user.name}).from(user);
for ( let row of rows ) {
if ( row.activity ) {
const activityJson = JSON.parse(row.activity);
const compactedActivity = await jsonld.compact(activityJson, ["https://www.w3.org/ns/activitystreams"]);
promptStart();
const {domain} = await promptGet(['domain']);
// ID to match API url format.
compactedActivity.id = `https://${domain}/api/activitypub/user/${row.name}`;
// Ensure we have the up to date public key.
const secKeyRow = await db.select({publicKey: pubPrivKeys.publicKey, privateKey: pubPrivKeys.privateKey, id: pubPrivKeys.id}).from(pubPrivKeys).where(eq(pubPrivKeys.id, row.id)).orderBy(desc(pubPrivKeys.id));
if ( secKeyRow[0].publicKey !== null && secKeyRow[0].privateKey !== null ) {
compactedActivity["https://w3id.org/security#publicKey"] = {
id: `https://${domain}/api/activitypub/user/${row.name}#main-key`,
owner: `https://${domain}/api/activitypub/user/${row.name}`,
"https://w3id.org/security#publicKeyPem": secKeyRow[0].publicKey
}
} else {
const keyPair = await generateKeyPair('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem'
}
});
await db.insert(pubPrivKeys).values({
user: row.id,
publicKey: keyPair.publicKey,
privateKey: keyPair.privateKey
})
compactedActivity["https://w3id.org/security#publicKey"] = {
id: `https://${domain}/api/activitypub/user/${row.name}#main-key`,
owner: `https://${domain}/api/activitypub/user/${row.name}`,
"https://w3id.org/security#publicKeyPem": keyPair.publicKey
}
}
await db.update(user).set({activity: JSON.stringify(compactedActivity, null, 4)});
}
}
}
main();

5
types/jsonld.d.ts vendored Normal file
View file

@ -0,0 +1,5 @@
import { ContextDefinition } from "jsonld";
declare module 'jsonld' {
export function compact(input: JsonLdDocument, ctx?: ContextDefinition|(ContextDefinition|string)[]|string, options?: Options.Compact): Promise<JsonLdObj>;
}